AI 엔지니어링 — 딥다이브 학습 노트
채널: 뉴런데브 | 에피소드: 20개 | 대상: 7년차 Spring/Java 개발자 수준 교재: AI 엔지니어링 (서적 기반)
학습 로드맵
[Part 1: AI 제품과 LLM 기초]
EP1 AI 제품 ──→ EP2 LLM과 서비스 ──→ EP3 수학적 기초
│
▼
[Part 2: LLM 아키텍처] EP4 LLM 구조 1(MoE, Flash Attn, KV캐시, GQA)
│
▼
EP5 LLM 구조 2(위치 인코딩: RoPE→ALiBi→NTK→LongRoPE→YaRN)
│
▼
EP6 트랜스포머 대안(SSM/S4/맘바/잠바)
│
[Part 3: 모델 튜닝/경량화] EP7 SFT, RLHF, DPO ──→ EP8 양자화, 할루시네이션
│
[Part 4: 모델 평가] EP9 평가 개요(PPL) ──→ EP10 PPL 계산, LLM-as-Judge
│
EP11 평가 기준 ──→ EP12 앱 평가 1 ──→ EP13 앱 평가 2
│
[Part 5: 모델 선택/프롬프트] EP14 모델 선택 ──→ EP15 모델별 프롬프트 ──→ EP16 고급 프롬프트
│
[Part 6: RAG/에이전트] EP17 RAG ──→ EP18 에이전트와 도구
│
[Part 7: 파인튜닝/운영] EP19 파인튜닝/LoRA ──→ EP20 학습 실전/인퍼런스 운영
EP1. AI 제품에 대해
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 파운데이션 모델 | GPT-4, Gemini처럼 대규모 데이터로 미리 학습된 범용 AI 모델. 직접 만드는 게 아니라 가져다 쓰는 것 | JDK 같은 것. JDK를 직접 만들지 않고 Oracle/OpenJDK에서 가져다 쓰는 것과 같다 |
| 사전학습(Pre-training) | 인터넷의 방대한 텍스트로 언어의 기본 패턴을 학습하는 단계. 엄청난 비용(수십~수백억) | Java 컴파일러가 문법을 이해하도록 만드는 것. 우리가 할 일이 아님 |
| 사후학습(Post-training) | 사전학습된 모델을 특정 용도에 맞게 추가 학습하는 단계 (SFT, RLHF 등) | Spring Boot 자동설정처럼 기본 프레임워크 위에 우리 설정을 얹는 것 |
| LLM (Large Language Model) | 대규모 언어 모델. ChatGPT, Claude, Gemini 등이 대표적 | 거대한 "자동완성 엔진"이라고 생각하면 됨. 앞 문장을 보고 다음 단어를 예측 |
| 프로슈머(Prosumer) | Producer + Consumer. 직접 콘텐츠를 생산하는 소비자 | 개발자가 오픈소스를 쓰면서(소비) 동시에 기여(생산)하는 것과 비슷 |
| SFT (Supervised Fine-Tuning) | 정답이 있는 데이터로 모델의 출력 방향을 조정하는 학습 | 기존 라이브러리를 커스텀 설정으로 동작을 바꾸는 것 |
| LoRA | 모델 전체를 수정하지 않고 작은 어댑터만 추가하여 효율적으로 학습하는 기법 | AOP(관점 지향 프로그래밍)처럼 원본 코드를 건드리지 않고 기능을 추가하는 것 |
| 인퍼런스(Inference) | 학습이 끝난 모델에 질문을 넣고 답변을 받는 과정 | model.predict(input) 호출. 학습=빌드, 인퍼런스=런타임 실행 |
핵심 요약
AI 엔지니어링은 AI가 서비스의 핵심(30~40% 이상)을 차지하는 서비스를 체계적으로 만드는 방법론이다. AI 애플리케이션은 인프라/모델/애플리케이션 3계층으로 구성되며, "빨리 런칭"이 최우선 전략이다.
딥다이브
AI 애플리케이션 3계층
[애플리케이션] 프론트엔드(Streamlit, Open UI) + 백엔드(LangChain, Spring AI)
│ → Spring 개발자라면: Spring AI가 LangChain의 Java 버전이라고 생각
│
[모델] 파운데이션 모델 → 사전학습 / 사후학습(SFT) / 경량 튜닝(LoRA)
│ → 우리가 만드는 게 아니라 "선택"하는 것. OpenAI API 호출처럼
│
[인프라] GPU 서버 / 클라우드 / 외부 API
→ AWS/GCP에 배포하듯이, 모델도 클라우드에서 API로 사용
Spring 개발자 관점: 기존 Spring MVC 앱 3계층(Controller/Service/Repository)과 구조가 같다. 애플리케이션=Controller, 모델=Service(비즈니스 로직), 인프라=Repository(데이터소스). 차이점은 Service 계층이 "내가 짠 코드"가 아니라 "외부 AI 모델 API 호출"이라는 것.
서비스 타겟 전략
| 타겟 | 현실 | 전략 |
|---|---|---|
| B2C | ChatGPT 점유율 74~82%, 순수 B2C 성공 극히 어려움 | 기존 서비스에 AI 추가 (듀오링고 모델) |
| B2B | 기업용 도구, 커스텀 솔루션 | 도메인 특화, 에이전트 사고 |
| 프로슈머 | 생산 활동하는 소비자 | AI 서비스의 주요 수익 대상 |
왜 B2C가 어려운가?: ChatGPT가 이미 "포털 사이트"를 장악한 것과 같다. 네이버 검색에 정면 도전하는 것보다, 특정 분야(부동산, 의료)에서 네이버보다 나은 서비스를 만드는 게 현실적인 것과 같은 이치.
AI 서비스 개발 전략: "빨리 빨리"
- 인프라: 클라우드 + 외부 API 우선 (직접 구축은 람보르기니급 비용, 약 4억원)
- 비유: IDC 직접 운영 vs AWS 사용. 초기엔 무조건 AWS(= API) 사용
- 모델: 파운데이션 모델 튜닝은 노코드 도구(라마 팩토리, H2O) 활용
- 비유: Spring Initializr로 프로젝트 생성하듯, 노코드 UI로 모델 튜닝
- 데이터셋: 전문 업체(솔트룩스, 플리토, 클라우드워크스)에 외주
- 비유: 디자인을 직접 하지 않고 디자이너에게 맡기는 것
- 프론트/백: Streamlit + LangChain으로 빠르게
- Streamlit = Python용 간단한 웹 UI 프레임워크 (Spring Boot + Thymeleaf의 초간단 버전)
- LangChain = AI 모델 호출을 쉽게 해주는 프레임워크 (RestTemplate/WebClient의 AI 버전)
실무 체크포인트
- [ ] AI 서비스의 AI 비중이 30% 이상인지 명확히 정의했는가?
- [ ] 직접 구축 대신 기존 API/도구 활용을 먼저 검토했는가?
- [ ] Spring AI 또는 LangChain 중 어떤 프레임워크를 쓸지 결정했는가?
EP2. LLM과 서비스
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 모델 API | AI 모델을 HTTP API로 호출하는 것. REST API처럼 요청-응답 구조 | RestTemplate.postForObject("https://api.openai.com/...", request, Response.class) |
| vLLM | 오픈소스 모델을 고성능으로 서빙하는 엔진. 자체 서버를 운영할 때 사용 | Tomcat이 Java 앱을 서빙하듯, vLLM이 AI 모델을 서빙하는 것 |
| 에이전트(Agent) | LLM이 스스로 판단하여 도구(검색, API 호출 등)를 사용하며 문제를 해결하는 구조 | Spring Batch의 Step처럼 여러 단계를 자동으로 진행하되, 각 단계를 AI가 판단 |
| 토큰(Token) | LLM이 텍스트를 처리하는 기본 단위. 한글은 보통 한 글자=1~2토큰 | 컴파일러의 lexer가 소스코드를 토큰으로 분리하는 것과 같은 원리 |
| Ollama | 로컬 PC에서 오픈소스 LLM을 쉽게 실행할 수 있는 도구 | Docker Desktop처럼 로컬에서 모델을 pull하고 run하는 것 |
핵심 요약
모델을 공부하는 이유는 만들기 위해서가 아니라 서비스에 적합한 모델을 고르기 위해서다. 서비스 기획의 세 가지 사고방식 — 모델 중심, 서비스 중심, 에이전트 사고.
핵심 마인드셋: Spring 개발자가 MySQL vs PostgreSQL vs MongoDB를 고르듯, AI 엔지니어는 GPT-4 vs Claude vs Gemini vs Llama를 고른다. DB를 직접 만들지 않듯, AI 모델도 직접 만들지 않는다.
딥다이브
모델 API 선택 전략
| 구분 | 대표 | 장점 | 단점 | Spring 비유 |
|---|---|---|---|---|
| 메이저 API | OpenAI, Google, Anthropic | 범용, 다양한 부가 API | 비용, 다운타임 | AWS RDS (관리형 DB) |
| 특화 API | 업스테이지(PDF), TTS 등 | 도메인 품질 높음, 비용 효율적 | 범위 제한 | ElasticSearch (검색 특화) |
| 오픈소스 API | Ollama Cloud 등 | 저렴, 튜닝 모델 탑재 | 안정성 | MariaDB (무료 대안) |
| 자체 구축 | vLLM + GPU 서버 | 완전 통제 | 4억원(람보르기니급) | 직접 IDC 구축+DBA 운영 |
"API 비용이 비싸다고 느낄 정도면 성공한 서비스다" — AWS 비용이 부담되려면 트래픽이 많아야 하듯, API 비용이 부담되려면 사용자가 많아야 한다.
서비스 기획 3가지 사고방식
| 사고방식 | 설명 | 적합 시나리오 | 쉬운 비유 |
|---|---|---|---|
| 모델 중심 | 모델/API 능력 기반 서비스 설계 | 맨 땅에서 시작 | "이 기술로 뭘 만들 수 있지?" |
| 서비스 중심 | 편익 우선, 기술은 후속 | 기존 서비스에 AI 투입 (듀오링고) | "고객이 불편한 게 뭐지?" |
| 에이전트 | 편익 실현 도구 = AI 에이전트 | B2B/프로슈머에서 성공 | "AI가 사람 대신 일하게 하자" |
에이전트 사고의 예시: 기존에 사람이 수동으로 하던 작업(보고서 분석, 데이터 정리, 이메일 분류)을 AI 에이전트가 자동으로 수행. 고객 입장에서 "사람 한 명 고용한 효과"를 느끼게 하는 것이 핵심.
실무 체크포인트
- [ ] 메이저 API vs 특화 API vs 오픈소스 중 비용 대비 효과를 비교했는가?
- [ ] 서비스 기획 시 세 가지 사고방식 중 적합한 것을 선택했는가?
- [ ] API 호출 비용을 월 단위로 시뮬레이션해봤는가? (토큰당 가격 × 예상 사용량)
EP3. LLM의 수학적 기초
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 신경망(Neural Network) | 인간 뇌의 뉴런 연결을 모방한 수학적 모델. 입력→계산→출력 구조 | 여러 층의 Function<Input, Output>이 체인으로 연결된 것 |
| 파라미터(Parameter) | 신경망 내부의 숫자(가중치). 학습 = 이 숫자들을 조정하는 과정 | 설정 파일의 값들. GPT-4는 수천억 개의 설정값을 가진 것 |
| 학습(Training) | 데이터를 반복적으로 보여주며 파라미터를 조정하는 과정 | JUnit 테스트를 돌리면서 코드를 반복 수정하는 것과 비슷. 자동화된 튜닝 |
| 그래디언트(Gradient) | "이 파라미터를 어느 방향으로 얼마나 바꿔야 하는지" 알려주는 값 | 컴파일 에러 메시지와 비슷. "여기를 이렇게 고치면 결과가 좋아진다" |
| 역전파(Backpropagation) | 출력에서 입력 방향으로 그래디언트를 전달하여 파라미터를 업데이트하는 알고리즘 | Stack trace처럼 에러를 역추적하여 원인을 찾고 수정하는 과정 |
| 활성화 함수 | 신경망에 비선형성을 추가하는 함수. 없으면 아무리 층을 쌓아도 단순 직선 | if-else 분기와 비슷. 없으면 아무리 코드를 길게 써도 결국 return a*x + b |
| 트랜스포머(Transformer) | 2017년 구글이 발명한 신경망 구조. 현재 모든 LLM의 기반 아키텍처 | Spring Framework처럼 모든 현대 AI의 기반이 되는 프레임워크 |
| 어텐션(Attention) | "입력의 어느 부분에 집중할지" 결정하는 메커니즘. 트랜스포머의 핵심 | SQL의 WHERE절처럼 "어떤 데이터가 중요한지" 필터링하는 것 |
핵심 요약
정해(방정식)와 통계적 해(근사)의 차이를 이해하고, 신경망은 "엄청나게 많은 변수로 된 수학적 식"이며 편미분 그래디언트가 AI 발전의 핵심 전환점이다.
딥다이브
정해 vs 통계적 해
정해: x + 3 = 5 → x = 2 (유일한 답, 가우스 소거법)
통계적 해: "총무가 줌 방 여는 시간" → 56분 27초쯤 (근사, 모든 샘플과 불일치)
Java 비유: - 정해 =
Math.sqrt(4)→ 항상 정확히 2.0 - 통계적 해 = 머신러닝 예측 → "아마 2.03일 것이다" (근사값) - LLM은 통계적 해를 사용하므로 "항상 정확한 답"을 기대하면 안 됨
통계적 해법 스펙트럼
| 기법 | 설명 | 쉬운 비유 | 현재 |
|---|---|---|---|
| 로지스틱 회귀 | A/B 분류 경계선 | 38선 치기. 이 선 위면 A, 아래면 B | 간단한 분류에 여전히 유용 |
| 선형 회귀 | 데이터를 관통하는 최적 직선 | 엑셀 추세선. "키가 크면 몸무게도 무겁다" | 기본 예측에 사용 |
| 의사결정트리 | Yes/No 반복 예측 규칙 | if-else 중첩. "열 있니? → 기침하니? → 코로나 의심" | XGBoost 등으로 발전 |
| 군집화 | 라벨 없이 특징 추출 → 그룹화 | 고객을 소비 패턴으로 자동 분류 | 고차원일수록 어려움 |
| 신경망 | 많은 변수 + 편미분으로 점진 조정 | 수천억 개 설정값을 자동 튜닝하는 거대 시스템 | 현재 주류 |
신경망의 핵심 원리
신경망 = 엄청나게 많은 변수(인자)로 된 수학적 식
│
├── 퍼셉트론: 입력값이 기준값을 넘는지 분류 (불연속 함수)
│ → 비유: if (input > threshold) return 1; else return 0;
│
├── 활성화 함수: 시그모이드, ReLU, GELU → 비선형 처리
│ → ReLU: Math.max(0, x) ← 이것만으로 복잡한 패턴 학습 가능!
│ → 비선형이 없으면 f(g(x)) = ax + b 직선 밖에 안 됨
│
└── 편미분 그래디언트: 데이터마다 변수를 점진적으로 조정
→ "이 파라미터를 0.001 올리면 결과가 좋아진다" → 반복
→ AI 발전의 핵심 전환점
왜 "트랜스포머만 배우면 되는가"? 로지스틱 회귀, 의사결정트리 등은 역사적 기초이며 이해는 필요하지만, 현재 ChatGPT, Claude, Gemini, Llama 등 모든 LLM은 트랜스포머 기반이다. Spring만 깊이 알면 대부분의 Java 백엔드를 개발할 수 있듯, 트랜스포머만 깊이 이해하면 대부분의 AI 엔지니어링이 가능하다.
실무 체크포인트
- [ ] 간단한 분류 문제에 신경망 대신 로지스틱 회귀를 먼저 시도했는가?
- [ ] "트랜스포머만 배우면 됨"을 이해하고 있는가?
- [ ] 신경망의 파라미터 수 = 모델 크기라는 것을 이해하고 있는가? (7B = 70억개 파라미터)
EP4. 최신 LLM 구조 1편
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 토큰 임베딩 | 단어(토큰)를 숫자 벡터(배열)로 변환한 것. "사과"→[0.2, 0.8, ...] | HashMap<String, float[]>에서 단어를 꺼내면 숫자 배열이 나오는 것 |
| 차원(Dimension) | 임베딩 벡터의 크기. 차원이 클수록 의미를 더 세밀하게 표현 | float[4096] vs float[128]. 배열이 클수록 더 많은 정보 저장 |
| FFN (Feed-Forward Network) | 트랜스포머 내부의 "계산 층". 입력을 받아 변환 후 출력하는 신경망 | Function<float[], float[]>. 입력 배열을 받아 변환하는 메서드 |
| GPU HBM | GPU의 메인 메모리. 용량 크지만 속도 느림 | 하드디스크. 크지만 느림 |
| GPU SRAM | GPU의 캐시 메모리. 용량 작지만 속도 매우 빠름 | L1/L2 CPU 캐시. 작지만 매우 빠름 |
| Q(Query), K(Key), V(Value) | 어텐션 계산의 3요소. "무엇을 찾을지(Q)", "어디에 있는지(K)", "실제 값(V)" | SQL과 비슷: Q=WHERE 조건, K=인덱스, V=SELECT 컬럼 |
| 멀티헤드 어텐션 | 여러 개의 어텐션을 병렬로 실행하여 다양한 관점에서 패턴 포착 | 여러 개의 Thread가 동시에 다른 관점으로 데이터를 분석하는 것 |
| 캐시(Cache) | 이전에 계산한 결과를 저장해두고 재사용하는 것 | Redis/Ehcache와 같은 원리. 이미 계산한 것을 다시 계산하지 않음 |
핵심 요약
LLM 발전의 두 축 — 의미 표현력(토큰 임베딩 차원 확장)과 계산 효율성(MoE, Flash Attention, KV 캐시, GQA). 토큰 임베딩 차원이 4,000 이상이면 MoE가 필수다.
왜 두 축이 중요한가?: 더 정확한 AI를 만들려면 임베딩 차원을 키워야 하는데, 차원이 커지면 계산량이 폭발한다. 정확성과 속도/비용의 균형 = LLM 아키텍처의 핵심 과제.
딥다이브
MoE (Mixture of Experts) — 전문가 혼합 모델
전체 토큰 임베딩 [d₁...d₁₀₀₀₀]
│
라우터(학습됨) → 전문가 3개 활성화 (전체 8개 중)
│
[d₁..d₃₀₀₀]만 FFN 적용 ← 계산량 3/8로 절감
쉬운 비유: 병원에 8명의 전문의가 있는데, 환자(토큰)마다 해당 분야 전문의 3명만 진료. 모든 의사가 모든 환자를 볼 필요 없음 → 비용 3/8로 절감.
Java 비유:
switch(라우터 판단)→ 8개 서비스 중 3개만 호출.@Conditional로 필요한 Bean만 로딩하는 것과 비슷.차원 4,000 이하가 아니면 통으로 FFN을 돌릴 수 없음 → MoE 필수. Gemma 3 등 최신 모델 대부분 사용.
Flash Attention — 빠른 어텐션 계산
기존: GPU HBM(느림) ↔ 계산 ↔ HBM 왕복 ← 데이터 이동이 병목
Flash: GPU SRAM(고속)에서 직접 계산 → HBM 이동 비용 제거
쉬운 비유: 기존 방식 = 책상(SRAM)이 좁아서 매번 서재(HBM)에 가서 책을 가져옴. Flash Attention = 필요한 책만 조금씩 가져와서 책상에서 다 처리.
Java 비유: 기존 = 매번 DB에서 SELECT. Flash = 인메모리 캐시(Redis)에서 처리.
KV 캐시 — Key/Value 재활용
어텐션 계산 시:
Q(Query): 현재 토큰에 대해 매번 새로 계산 (캐시 불가)
K(Key), V(Value): 이전 토큰과 수학적으로 동일 → 캐시 재활용
예시: "나는 학생이다. 나는"에서 "나는 학생이다"의 K/V는 이미 계산했으므로 재사용
→ 새 토큰 "나는"에 대한 Q만 새로 계산
KV 캐시 양자화: FP16 → FP8/INT8로 저장하여 메모리 절약
Java 비유: HTTP 세션에 이전 요청 결과를 저장해두고, 새 요청에서 재사용하는 것.
session.getAttribute("previousKV")→ 있으면 재활용, 없으면 새로 계산.
GQA (Grouped Query Attention) — 그룹별 질의 어텐션
기존 멀티헤드: Q, K, V 모두 헤드별 독립 계산 → 비용 높음
GQA: Q는 그룹별 고정 파라미터(학습시 결정), K/V만 토큰 영향 반영
→ Q 계산 비용 절감, 최신 모델 대부분 채택
쉬운 비유: 기존 = 각 팀원이 각자 질문을 만들어 검색. GQA = 팀별로 공통 질문을 미리 정해두고, 답변(K/V)만 각 문서에서 찾음.
실무 체크포인트
- [ ] 모델 아키텍처 문서에서 MoE 사용 여부와 전문가 수를 확인했는가?
- [ ] KV 캐시가 인퍼런스 엔진에서 자동 처리되는지 확인했는가?
- [ ] 모델 카드에서 임베딩 차원(Hidden Size)과 헤드 수를 확인했는가?
EP5. 최신 LLM 구조 2편
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 위치 인코딩 | 토큰의 순서(위치) 정보를 벡터에 추가하는 기법. 없으면 "나는 밥을 먹다"와 "밥을 나는 먹다"를 구별 못함 | 배열의 인덱스. list.get(0)과 list.get(5)의 차이를 아는 것 |
| 벡터(Vector) | 숫자들의 배열. 임베딩은 고차원 벡터 | float[] 또는 List<Float>. [0.2, 0.8, -0.3, ...] |
| 코사인 유사도 | 두 벡터가 얼마나 같은 방향을 가리키는지 측정 (-1~1). 의미 유사도 측정에 사용 | 두 float[]이 얼마나 비슷한지 계산. 1이면 동일 방향, 0이면 무관 |
| 외삽(Extrapolation) | 학습 범위를 벗어난 데이터에 대한 예측. 예: 4K 토큰으로 학습한 모델에 128K 토큰 입력 | ArrayList(10)에 인덱스 1000을 접근하는 것. 범위 밖 처리 능력 |
| OOD (Out-of-Distribution) | 학습 시 보지 못한 분포의 데이터. 모델이 잘 처리하지 못할 가능성이 높음 | 테스트에 없던 엣지 케이스. 개발 시 고려하지 않은 입력값 |
| 컨텍스트 길이/윈도우 | 모델이 한 번에 처리할 수 있는 최대 토큰 수. GPT-4: 128K, Claude: 200K | StringBuilder의 최대 용량과 비슷. 초과하면 처리 불가 |
핵심 요약
위치 인코딩의 진화 — 절대 위치 → RoPE(회전) → ALiBi(선형 페널티) → NTK(동적 스케일링) → LongRoPE(선택적 스케일링) → YaRN(보정). 현대 모델은 대부분 RoPE 변형을 사용한다.
왜 위치 인코딩이 필요한가? 트랜스포머는 모든 토큰을 동시에 처리(병렬)하므로 순서를 모른다. "개가 사람을 물었다" vs "사람이 개를 물었다"를 구별하려면 위치 정보가 필수. 이를 해결하기 위해 각 토큰에 "너는 3번째 단어야"라는 정보를 추가하는 것이 위치 인코딩.
딥다이브
위치 인코딩 진화 비교
| 기법 | 원리 | 장점 | 한계 | 현재 |
|---|---|---|---|---|
| 절대 위치 | 위치값 더하기 | 단순 | 벡터 유사도 오류, 외삽 불가 | 폐기 |
| RoPE | 벡터 회전(라디안) | 상대 거리 학습, 크기 보존 | 학습 길이 초과 시 OOD | 기반 기술 |
| ALiBi | 거리 비례 선형 페널티 | 학습 불필요, 고속 | 선형 함수 한계, 긴 컨텍스트 트레이드오프 | 현재 안 씀 |
| NTK | 동적 스케일링 | 길이 초과 시 각도 겹침 방지 | 긴 문맥에서 회전 각도 너무 작아짐 | 보조 기법 |
| LongRoPE | 단거리 고주파 + 장거리 저주파 분리 | NTK 부작용 해결 | 복잡 | 주류 |
| YaRN | 어텐션 템퍼처 보정 | RoPE 변형과 독립 적용 | 추가 보정 단계 | 보조 기법 |
RoPE의 핵심: 회전으로 위치 표현
벡터를 "회전"시킴 → 벡터 크기(의미 정보)는 보존, 각도만 변화
비유: 지름 1cm 선분을 돌리기만 함 → 길이는 언제나 1
상대 거리: 회전 각도의 차이 = 두 토큰 간 거리
→ 더하기(절대 위치)보다 우수: 유사도 오류 없음
쉬운 비유 — 시계: - 절대 위치 = "3시에 만나자" → 위치를 숫자로 더함. 문제: 시계가 12까지만 있음 - RoPE = "지금부터 2시간 후" → 상대적 시간차. 몇 시에 시작하든 2시간 차이는 동일 - NTK = 시계 눈금을 더 잘게 나눠서 12시간 이상도 표현. 단 너무 잘게 나누면 읽기 어려움 - LongRoPE = 가까운 시간은 "분 단위"(정밀), 먼 시간은 "시간 단위"(대략적)로 분리
LongRoPE가 주류인 이유
문제: 4K 토큰으로 학습한 모델에 128K 토큰을 입력하면?
→ RoPE: 학습 범위 밖이므로 위치 정보 엉망 (OOD)
→ NTK: 전체 스케일을 줄임 → 가까운 토큰끼리도 구별 어려워짐
LongRoPE의 해결:
가까운 토큰 (1~1000번째): 고주파(정밀한 회전) → 세밀하게 구별
먼 토큰 (1000~128K번째): 저주파(느린 회전) → 대략적으로 구별
→ 가까운 것은 정밀하게, 먼 것은 대략적으로 = 인간의 기억과 비슷!
실무 체크포인트
- [ ] 모델 문서에서 어떤 위치 인코딩을 사용하는지 확인했는가?
- [ ] 긴 컨텍스트 모델의 외삽 성능을 벤치마크로 검증했는가?
- [ ] 모델의 최대 컨텍스트 길이와 실제 서비스에서 필요한 길이를 비교했는가?
EP6. 트랜스포머 대체 신경망 연구
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| O(n²) 복잡도 | 입력 크기 n이 2배 되면 계산량이 4배 증가하는 복잡도 | 중첩 for문 for(i) for(j). 데이터 1000개면 100만 번 계산 |
| SSM (State Space Model) | 시퀀스를 순차적 상태로 처리하는 모델. 이전 상태가 다음 상태에 영향 | for 루프에서 이전 결과를 다음 반복에 사용하는 것. 상태 기계(State Machine) |
| 하이브리드 아키텍처 | 두 가지 이상의 아키텍처를 혼합하여 각각의 장점을 취하는 구조 | @Configuration에서 JPA와 MyBatis를 동시에 사용하는 것 |
| 시퀀스(Sequence) | 순서가 있는 데이터의 나열. 텍스트, DNA, 주가 등 | List<Token>. 순서가 의미를 가지는 데이터 |
핵심 요약
트랜스포머는 기하급수적 자원 소비와 토큰 순서 인식 불가라는 근본적 한계가 있다. SSM/S4/맘바가 대안으로 연구되며, 잠바(Jamba)는 맘바+트랜스포머 하이브리드로 긴 시퀀스에 강하다. 그러나 범용 대형 LLM 대체는 불가하다.
딥다이브
트랜스포머의 근본적 한계
- 기하급수적 자원 소비: 모든 토큰이 모든 토큰에 어텐션 → O(n²)
- 1K 토큰: 100만 번 계산
- 128K 토큰: 164억 번 계산 (16,384배!)
- 비유: 회의실에 사람이 10명이면 45번 악수, 100명이면 4,950번 악수
- 토큰 순서 인식 불가: 어텐션은 동시에 서로를 봄, 순차적 상태 없음
- 비유: 모든 회의 참가자가 동시에 말하는 것. 누가 먼저 말했는지 모름
- → 위치 인코딩(EP5)으로 보완
SSM → S4 → 맘바 → 잠바
SSM (State Space Model): 시퀀스를 시간적 상태로 모델링
│ → 비유: for 루프처럼 순차 처리. 이전 결과가 다음에 영향
│ → O(n) 선형 복잡도! 트랜스포머의 O(n²)보다 훨씬 효율적
│
└→ S4: 적분 함수(커널)로 병렬 계산 가능하게 만듦
│ → SSM의 순차 처리를 GPU 병렬 처리로 변환
│
└→ 맘바 (Mamba): S4 개선. 입력에 따라 동적으로 상태 변환
│
└→ 잠바 (Jamba): 맘바 레이어 + MoE + 트랜스포머 레이어 혼합
→ "좋은 것만 섞자!" 전략
Java 비유: SSM =
for루프 (순차, O(n)). 트랜스포머 = 중첩for(O(n²)). 짧은 데이터면 둘 다 빠르지만, 데이터가 128K개면 O(n) vs O(n²)의 차이가 극명해짐.
잠바의 위치
| 구분 | 트랜스포머 | 잠바 (하이브리드) | 쉬운 설명 |
|---|---|---|---|
| 30B 이하 | 경쟁적 | 경쟁적, 긴 시퀀스에서 우위 | 작은 모델에서는 호각 |
| 120B+ | 압도적 | 범용 대체 불가 | 대형 범용 AI는 트랜스포머가 압승 |
| DNA/주가 분석 | 보통 | 압도적 성능 | 긴 시계열 데이터는 맘바가 최적 |
결론: 트랜스포머 = 범용 "만능 도구". 맘바/잠바 = 긴 시퀀스 "특수 도구". Spring MVC가 대부분의 웹 앱에 적합하듯, 트랜스포머가 대부분의 AI에 적합. 하지만 WebFlux가 특정 시나리오에서 우위이듯, 맘바도 특정 도메인에서 우위.
실무 체크포인트
- [ ] 긴 시퀀스 처리(DNA, 시계열)에서 맘바/잠바 기반 모델을 검토했는가?
- [ ] 범용 LLM에는 트랜스포머가 여전히 최선임을 이해하고 있는가?
- [ ] 입력 시퀀스가 얼마나 긴지 파악하여 아키텍처 선택에 반영했는가?
EP7. 모델 튜닝 — SFT, RLHF, DPO
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| SFT (Supervised Fine-Tuning) | 정답이 있는 데이터(질문→답변)로 모델의 출력 방향을 조정하는 학습 | JUnit 테스트에서 기대값(expected)을 주고, 코드가 그 답을 내도록 수정하는 것 |
| RLHF | 사람이 "A가 B보다 낫다"고 평가 → 보상 모델 학습 → 모델을 보상 최대화 방향으로 튜닝 | 코드 리뷰에서 시니어가 "이 코드가 더 좋아"라고 피드백 → 그 방향으로 수정 |
| DPO (Direct Preference Optimization) | RLHF에서 보상 모델을 생략하고, 선호/비선호 쌍으로 직접 학습 | 코드 리뷰에서 "이게 좋다/이게 나쁘다" 쌍만으로 바로 학습. 중간 단계 생략 |
| 보상 모델(Reward Model) | "이 응답이 얼마나 좋은지" 점수를 매기는 별도의 AI 모델 | SonarQube 같은 코드 품질 검사기. 코드를 넣으면 점수가 나옴 |
| PPO (Proximal Policy Optimization) | 보상값이 너무 급격히 변하지 않도록 조절하는 최적화 알고리즘 | Math.min(변화량, 상한선)처럼 급격한 변화를 방지하는 클램핑 |
| 로그 프로브(Log Probability) | 모델이 각 토큰을 생성할 확률의 자연로그값. 모델의 "확신도"를 수치화 | Math.log(probability). 확률 0.9 → -0.10 (확신), 확률 0.1 → -2.30 (불확신) |
| 인스트럭션(Instruction) | 모델에게 주는 지시사항. 시스템 프롬프트의 핵심 내용 | Controller의 요청 매핑 어노테이션처럼 "이 입력이 오면 이렇게 처리해" |
| 시스템 프롬프트 | 대화 시작 전 모델에게 주는 역할/규칙 설정 | application.yml의 설정값. 앱 실행 전에 동작 방식을 정하는 것 |
핵심 요약
SFT로 답변 방향을 조정하고, RLHF/DPO로 인간 선호도를 반영한다. DPO가 보상 모델 없이 직접 최적화하므로 더 효율적이다. 시스템 프롬프트의 효과는 SFT 인스트럭션 학습 범위에 의존한다.
모델 학습의 3단계 흐름:
사전학습 → SFT → RLHF/DPO (언어 이해) (답변 방향) (품질 향상)Java로 비유하면: JDK 설치 → Spring Boot 설정 → 코드 리뷰/리팩토링
딥다이브
SFT (Supervised Fine-Tuning) — 지도 미세 조정
데이터: [인스트럭션] + [인풋] → [아웃풋]
예: [Translate] + [I love] → [Je t'aime]
핵심: 질문 쪽은 기존 모델 사용, 답변 쪽만 학습
→ 출력 방향만 변경, 기존 지식은 보존
쉬운 비유: 영어를 할 줄 아는 사람(사전학습)에게 "번역가로 일하라"고 교육(SFT). 영어 실력 자체는 건드리지 않고, "번역 방식"만 학습시키는 것.
인스트럭션의 4가지 구성 요소
| 요소 | 설명 | 예시 | Spring 비유 |
|---|---|---|---|
| 역할 | 모델의 페르소나 | "너는 수학 교사야" | @Component("mathTeacher") |
| 지시 | 구체적 작업 지시 | "학생 수준에 맞게 설명해" | @RequestMapping 핸들러 |
| 맥락 | 상황 배경 | "초등학교 3학년 대상" | @Profile("elementary") |
| 기대 | 출력 형식/조건 | "3문장 이내로 답변" | @ResponseBody 형식 지정 |
시스템 프롬프트가 안 먹히는 모델 = SFT 학습을 안 했거나, 인스트럭션 없이 학습한 모델. 비유:
@RequestMapping을 처리하는 DispatcherServlet 설정이 안 된 것.
RLHF vs DPO — 인간 선호도 학습
| 구분 | RLHF | DPO |
|---|---|---|
| 보상 모델 | 필요 (별도 학습) | 불필요 |
| 학습 비용 | 높음 | 낮음 |
| 인간 레이블 | 필요 | 선택/리젝 쌍만 |
| 방식 | 선호도 → 보상값 → PPO | 로그 프로브 차이로 직접 학습 |
| 채택 | 초기 모델 | Gemini 등 최신 모델 |
RLHF 과정 (3단계):
1. 사람이 응답 A > B 라고 평가
2. 이 데이터로 보상 모델 학습 (A에 높은 점수, B에 낮은 점수)
3. 보상 모델 점수를 최대화하는 방향으로 LLM 튜닝 (PPO)
DPO 과정 (1단계):
1. 선택(좋은 응답) / 리젝(나쁜 응답) 쌍으로 직접 LLM 튜닝
→ 보상 모델 없이 로그 프로브 차이만으로 학습
→ RLHF의 2,3단계를 한 번에 해결!
쉬운 비유: - RLHF = 음식 평가단(보상 모델)을 먼저 훈련시키고 → 평가단 점수를 보고 요리사가 개선 - DPO = "이 음식이 저 음식보다 맛있다"는 비교 결과만으로 요리사가 직접 개선. 평가단 불필요
⚠️ 최신 업데이트: DPO vs RLHF (2025-2026)
2025년 기업의 70%가 RLHF/DPO를 사용하며, DPO 채택이 2024년 45% 급증했다. 최신 연구에 따르면 RLHF, DPO, 온라인 DPO는 모델 오명세(mis-specification) 유형에 따라 서로 우위가 달라지며, 어느 쪽이 보편적으로 우월하지 않다. 온라인 DPO는 보상 모델과 정책 모델이 동형이고 둘 다 오명세일 때 양쪽을 모두 능가할 수 있다.
LoRA를 이용한 경량 RLHF
마지막 어텐션 레이어의 FFN 뒤에 경량 레이어를 추가하여 RLHF 효과를 얻는 기법. 모델 전체 학습 없이도 비슷한 효과.
비유: 기존 건물(모델) 전체를 리모델링(RLHF)하는 대신, 옥상에 작은 구조물(LoRA)만 올려서 비슷한 효과를 내는 것.
실무 체크포인트
- [ ] 시스템 프롬프트 효과가 부족하면 SFT 인스트럭션 학습 범위를 확인했는가?
- [ ] DPO와 RLHF 중 도메인에 맞는 것을 선택했는가?
- [ ] 선택/리젝 데이터 쌍을 충분히 확보했는가? (DPO 기준 최소 수백~수천 쌍)
EP8. 양자화 및 할루시네이션
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 양자화(Quantization) | 숫자의 정밀도를 줄여 메모리와 계산량을 절감하는 기법 | double → float → short로 변환. 정밀도는 줄지만 메모리 절약 |
| FP32/FP16/FP8 | 부동소수점 숫자의 정밀도. 32비트(4바이트) → 16비트(2바이트) → 8비트(1바이트) | double(8B) → float(4B). 정밀도↓ 속도↑ 메모리↓ |
| INT8/INT4 | 정수형 양자화. 소수점 없이 정수로 표현. NPU에서 고속 동작 | int → short → byte. 소수점 버리고 정수로 빠르게 계산 |
| NPU | Neural Processing Unit. AI 계산에 특화된 프로세서. 스마트폰에 내장 | GPU가 그래픽 특화 프로세서이듯, NPU는 AI 추론 특화 프로세서 |
| 할루시네이션 | LLM이 사실과 다른 내용을 그럴듯하게 생성하는 현상. "헛소리" | 컴파일은 되지만 런타임에 잘못된 결과를 내는 논리 버그와 비슷. 단, AI에서는 버그가 아닌 본질 |
| Temperature | LLM의 출력 다양성을 조절하는 값. 0에 가까우면 가장 확률 높은 답, 1이면 다양한 답 | Random.nextGaussian()의 표준편차와 비슷. 낮으면 보수적, 높으면 모험적 |
| Top-P (Nucleus Sampling) | 확률 합이 P(예: 0.9)가 되는 상위 토큰들만 후보로 선택 | 정렬된 리스트에서 상위 90%만 subList로 잘라서 그 안에서 선택 |
| RAG | Retrieval-Augmented Generation. 외부 문서를 검색하여 LLM 입력에 추가하는 기법 | DB에서 관련 데이터를 조회(SELECT)하여 API 응답에 포함시키는 것 |
핵심 요약
양자화는 숫자 정밀도를 줄여 메모리/계산량을 절감하는 기법이다. 메모리를 절반으로 줄여도 품질 저하는 10~20% 수준이다. 할루시네이션은 LLM의 버그가 아니라 확률적 토큰 생성의 본질적 특성이다.
딥다이브
양자화 종류
| 종류 | 대상 | 효과 | 쉬운 설명 |
|---|---|---|---|
| 모델 양자화 | K, V 파라미터, MLP/FFN 층 | 모델 크기 축소 | JAR 파일 압축. 5GB → 2.5GB |
| 활성화 양자화 | 인퍼런스 시 로딩된 파라미터/토큰 임베딩 | 연산 속도 향상 | 런타임에 int로 계산하여 속도 향상 |
| KV 캐시 양자화 | KV 캐시 정밀도 | 메모리 절약 | Redis 캐시를 압축 저장 |
정밀도 비교
FP32 (4바이트) → FP16 (2바이트, GPU 기본) → FP8 (1바이트) → FP4
↓
INT8 → INT4 → INT6 ← 정수 기반, NPU에서 고속 동작
예시: 숫자 3.141592653589793
FP32: 3.141592653589793 (거의 정확)
FP16: 3.140625 (약간 오차)
FP8: 3.0 (더 큰 오차)
INT8: 3 (소수점 없음)
→ 놀라운 점: 이렇게 정밀도를 줄여도 LLM 품질 저하는 10~20% 수준!
신경망은 정밀한 숫자보다 "대략적 패턴"이 중요하기 때문.
할루시네이션의 본질
LLM = "말짓기(confabulation) 시스템" = 확률적 토큰 선택기
LLM은 "다음에 올 확률이 가장 높은 단어"를 선택할 뿐.
실제로 그 내용이 사실인지는 전혀 검증하지 않는다.
첫 토큰이 잘못된 방향 → 확률적 일관성 유지 → 계속 잘못된 방향
비유: "한번 길을 잘못 들면, 그 길에서 가장 자연스러운 방향으로 계속 감"
핵심: 할루시네이션은 고칠 수 없는 본질이다. 줄일 수만 있다.
NullPointerException은 null 체크로 예방하듯, 할루시네이션은 RAG/프롬프팅으로 예방.
할루시네이션 보완 3가지
| 방법 | 설명 | 효과 | 쉬운 비유 |
|---|---|---|---|
| Top-P / Temperature 조정 | 확률 분포를 좁혀 안전한 토큰 선택 | 중 | 보수적 투자 (안전한 것만 선택) |
| 미세 조정 (SFT/DPO) | 학습 데이터로 방향 교정 | 중 | 신입 교육으로 실수 줄이기 |
| 프롬프팅 / RAG | 입력 토큰으로 올바른 방향 유도 | 대 | 오픈북 시험 (자료 보고 답하게) |
실무 최선: Temperature를 0.1~0.3으로 낮추고 + RAG로 관련 문서를 제공하면 할루시네이션을 80% 이상 줄일 수 있다.
실무 체크포인트
- [ ] 온디바이스 AI에서 INT8/INT4 양자화를 적용했는가?
- [ ] 할루시네이션 대응으로 Temperature 조정 + RAG를 병행하고 있는가?
- [ ] 사실 확인이 중요한 서비스에서 LLM 출력을 검증하는 후처리를 추가했는가?
EP9. LLM 모델 평가의 개요와 기준
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| PPL (Perplexity) | 모델이 다음 단어를 얼마나 잘 예측하는지의 척도. 낮을수록 좋음 | 테스트 커버리지와 비슷. PPL=1이면 100% 예측 성공, PPL=100이면 거의 랜덤 |
| 교차 엔트로피 | 두 확률 분포의 차이를 측정하는 수학적 방법 | expected.equals(actual)의 실패율을 수치화한 것 |
| 로짓(Logit) | 소프트맥스 적용 전의 원시 출력값. 확률로 변환되기 전 단계 | return 직전의 중간 계산값. 아직 정규화(확률 변환)되지 않은 raw 값 |
| 소프트맥스(Softmax) | 로짓을 확률(0~1 합=1)로 변환하는 함수 | 점수를 백분율로 변환. [2.0, 1.0, 0.5] → [0.59, 0.24, 0.17] |
| 코퍼스(Corpus) | 평가용 텍스트 데이터 모음. 도메인 텍스트를 모아놓은 것 | 테스트 데이터셋. src/test/resources/ 에 있는 테스트용 입력 데이터 |
| 벤치마크 | 모델 성능을 표준화된 문제로 측정하는 평가 체계 | JMH 벤치마크처럼 표준화된 성능 측정 도구 |
| 임베딩(Embedding) | 텍스트를 고정 크기 숫자 벡터로 변환한 것. 의미가 비슷하면 벡터도 비슷 | Objects.hashCode()의 의미론적 버전. 비슷한 것은 비슷한 값을 가짐 |
핵심 요약
모델이 좋으면 에이전트 개발이 최소화된다. 평가의 3축은 정확성, 의미적 유사도, 기능성이며, PPL(Perplexity)로 도메인 적합성을 측정한다.
핵심 마인드셋: 좋은 DB를 선택하면 쿼리 최적화 코드가 줄어들듯, 좋은 모델을 선택하면 프롬프트 엔지니어링/에이전트 코드가 줄어든다. 모델 선정에 1주일 투자하면 개발 1개월을 절약할 수 있다.
딥다이브
평가 3축
| 축 | 설명 | 방법 | 쉬운 비유 |
|---|---|---|---|
| 정확성 (재연율) | 학습 데이터를 얼마나 잘 재현 | 정답 비교 | 시험 정답률 |
| 의미적 유사도 | 같은 의미의 다른 표현 비교 | 임베딩/리랭커/LLM 평가 | "맞는 말이긴 한데 다른 표현" |
| 기능성 | 사람에게 쓸모 있는가 | 주관적, 사업 기준 | "정확하지만 쓸모없는 답 vs 약간 부정확하지만 유용한 답" |
교차 엔트로피와 PPL
교차 엔트로피: 학습 데이터와 평가 데이터 사이 확률 분포 교차 측정
→ 학습 적합성 수치화
PPL(Perplexity): 교차 엔트로피를 정규화
PPL = 1 → 완벽 예측 (모델이 이 도메인을 잘 안다)
PPL = 10 → 평균적 (보통 수준의 이해도)
PPL = 100 → 랜덤 수준 (모델이 이 도메인을 모른다)
예시:
의료 코퍼스로 GPT-4 평가 → PPL = 8 (잘 알고 있음)
의료 코퍼스로 코딩 특화 모델 평가 → PPL = 65 (잘 모름)
→ GPT-4가 의료 도메인에 더 적합
실무 핵심: 도메인 코퍼스로 PPL을 측정하면 모델의 도메인 적합성을 객관적으로 판단할 수 있다. NLP 모호성 없이 로짓 기반 순수 평가가 가능하다.
Java 비유: PPL = 단위 테스트 성공률의 역수. PPL이 낮을수록 = 테스트 통과율이 높을수록 = 해당 도메인에 적합한 모델.
실무 체크포인트
- [ ] 도메인 코퍼스를 준비하여 후보 모델들의 PPL을 비교했는가?
- [ ] 벤치마크 점수를 맹신하지 않고 실제 도메인 데이터로 검증했는가?
- [ ] PPL 측정이 어려우면 최소한 도메인 질문 30개로 수동 비교라도 했는가?
EP10. 퍼플렉시티와 AI로 모델 평가하기
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| LLM-as-Judge | LLM을 평가자로 사용하는 기법. 다른 LLM의 출력 품질을 AI가 판정 | SonarQube가 코드 품질을 자동 평가하듯, AI가 AI 출력을 평가 |
| 자연로그(ln) | 수학 함수. 확률의 곱을 합으로 변환하기 위해 사용 | Math.log(x). 아주 작은 소수의 곱셈(0.9×0.8×0.6)을 덧셈으로 변환 |
| exp (지수 함수) | e^x. 자연로그의 역함수. 로그 공간의 값을 원래 스케일로 복원 |
Math.exp(x). log로 변환한 것을 다시 원래 값으로 되돌리기 |
| 벤치마크 튜닝 | LLM 회사가 유명 벤치마크 문제를 학습 데이터에 포함시켜 점수만 높이는 행위 | 시험 족보를 외워서 시험 성적만 높이는 것. 실력이 아닌 점수만 상승 |
| 토너먼트 기법 | 여러 응답을 1:1 비교(A vs B 중 어느 것이 나은가?)하여 순위를 매기는 방법 | 축구 토너먼트처럼 1:1 대결로 우승자를 결정 |
핵심 요약
PPL 계산은 토큰별 확률의 로그(로그 프로브) 합산 → 정규화이다. LLM을 평가자로 쓸 때는 점수가 아닌 분류/부울린 판정으로 환원해야 한다. 벤치마크 튜닝에 주의해야 한다.
딥다이브
PPL 계산 과정
1. 소프트맥스 → 각 토큰의 확률: A=0.9, B=0.8, C=0.6, D=0.3
→ "나는 학생이다"에서 "나는"(0.9), "학생"(0.8), "이다"(0.6), "."(0.3)
→ 높은 확률 = 모델이 잘 예측한 것
2. 자연로그(-log): A=-0.10, B=-0.22, C=-0.51, D=-1.20
왜 로그?: 0.9 × 0.8 × 0.6 × 0.3 = 0.1296 (너무 작은 소수점!)
로그로 변환하면 덧셈으로: -0.10 + -0.22 + -0.51 + -1.20 = -2.03
3. 합산 = 교차 엔트로피 (단위: nat 또는 bit)
→ Java로 치면: double crossEntropy = -sumOfLogProbs / tokenCount;
4. exp(교차 엔트로피) = PPL → 단위 무관하게 동일값
→ Java로 치면: double ppl = Math.exp(crossEntropy);
LLM 평가자 사용 시 필수 규칙
| 하면 안 됨 | 해야 함 | 이유 |
|---|---|---|
| "몇 점인가요?" | True/False 분류 판정 | LLM은 계산이 아닌 말짓기로 점수를 생성. "2.7점"은 할루시네이션 |
| "2.7점" (계산이 아닌 말짓기) | 판정 합산 → 점수 산출 (토너먼트 기법) | boolean 판정의 합이 진짜 점수 |
| 1회 평가 | 5회 평가 → 극빈/최빈 제외 → 나머지 평균 | LLM은 확률적이므로 매번 다른 답. 여러 번 돌려야 안정 |
쉬운 비유: LLM에게 "이 코드 몇 점이야?"라고 물으면 "음... 7.3점요"라고 대충 답함 (할루시네이션). 대신 "이 코드에 버그가 있어? (Yes/No)"라고 물으면 정확한 판정 가능. 10가지 항목에 Yes/No를 물어서 Yes 개수 = 점수. 이것이 진짜 점수.
벤치마크 튜닝 주의
LLM 회사들이 유명 벤치마크에 SFT 튜닝하여 점수만 높이는 행위가 존재한다. 벤치마크 점수가 높아도 실사용에서 이상할 수 있다.
비유: TOEIC 만점이지만 실제 영어 대화를 못하는 사람. 리더보드 1위라도 우리 도메인에서 잘 동작하는지는 별개 문제. → 해결: 우리 도메인 데이터로 직접 PPL 측정하면 진짜 실력이 드러남.
실무 체크포인트
- [ ] LLM 평가자에게 점수 대신 분류 판정을 요청하고 있는가?
- [ ] 평가용 LLM과 대상 LLM의 도메인 PPL이 비슷한지 확인했는가?
- [ ] 벤치마크 점수만 보지 않고, 도메인 데이터로 직접 테스트했는가?
EP11. LLM 평가 기준과 방법
먼저 알아야 할 개념
| 용어 | 쉬운 설명 |
|---|---|
| MMLU | Massive Multitask Language Understanding. 57개 분야 객관식 문제로 지식 평가. 대학 수준 시험 |
| BBH (Big-Bench Hard) | 추론력 테스트. 논리, 수학, 언어 이해 등 어려운 문제 모음 |
| HumanEval | 코딩 능력 평가. Python 함수를 생성하고 테스트 케이스 통과 여부 확인 |
| Arena Hard | 사용자가 두 모델 응답을 비교하여 선호도를 매기는 실전 평가 |
| ELO 레이팅 | 체스에서 사용하는 상대적 실력 평가 시스템. Arena에서 모델 순위 매기는 데 사용 |
| 컴플리션(Completion) | 질문-답변 쌍으로 구성된 학습용 데이터 |
핵심 요약
평가 방법은 단일 평가(절대), 교차 평가(선호도), 유사도 평가 3가지이며, 5가지 평가 영역(지식/추론/대화/선호/안정성)으로 나뉜다. 모델 선정에 투자하면 에이전트 구현이 안정적이고 유지보수가 쉬워진다.
딥다이브
평가 방법 비교
| 방법 | 설명 | 비용 | 정확도 | 쉬운 비유 |
|---|---|---|---|---|
| 단일 평가 | 1~5 정수 점수 (분류에 가까움) | LLM 1회 | 높음 (할루시네이션 낮음) | 별점 평가 (1~5점) |
| 교차 평가 | A vs B 비교 | 높음 | 높음 | 블라인드 테스트 (어느 것이 나은지) |
| 유사도 평가 | 임베딩 기반 | 저렴 | NLP 보장 어려움 | 코사인 유사도로 "비슷한 정도" 측정 |
왜 1~5 정수인가?: "7.3점 주세요"라고 하면 LLM이 할루시네이션으로 점수를 생성. "1~5 중 하나만 골라"라고 하면 사실상 5개 클래스 분류 문제가 되어 정확도가 높아짐.
5가지 평가 영역
| 영역 | 대표 벤치마크 | 쉬운 설명 |
|---|---|---|
| 지식/이해력 | MMLU, MMLU-Pro | 대학 입시 수준 객관식. "이 분야를 아는가?" |
| 추론력 | BBH, GSM-8K/16K, MATH | 수학 문제, 논리 퍼즐. "생각할 수 있는가?" |
| 대화 품질 | Arena Hard | 실제 대화. "사람처럼 자연스러운가?" |
| 코드 | HumanEval, MBPP | 코딩 문제. "코드를 짤 수 있는가?" |
| 도메인 | MedQA, RECALL | 전문 분야. "의료/법률을 아는가?" |
학습 데이터 vs 평가 데이터
| 구분 | 컴플리션 (학습) | 코퍼스 (평가) |
|---|---|---|
| 구조 | 질문-답변 쌍 | 단일 팩트 나열 |
| 용도 | SFT 등 학습 | PPL 측정 |
| 비유 | 문제집 (문제+정답) | 교과서 (지식 나열) |
주의: 학습 데이터를 평가에 사용하면 안 됨 (시험에 같은 문제 출제와 같음). 평가용 코퍼스는 학습에 포함되지 않은 별도의 도메인 텍스트여야 함.
실무 체크포인트
- [ ] 도메인 특화 벤치마크가 없다면 도메인 코퍼스 PPL을 측정하고 있는가?
- [ ] 점수 스케일을 낮춰(1~5 정수) 할루시네이션을 줄였는가?
- [ ] HumanEval 점수(코딩)와 MMLU 점수(지식) 중 서비스에 더 중요한 것이 무엇인지 파악했는가?
EP12. AI 애플리케이션 평가 1
먼저 알아야 할 개념
| 용어 | 쉬운 설명 |
|---|---|
| 멀티턴(Multi-turn) | 여러 차례 대화를 주고받는 것. 이전 대화 맥락을 기억하며 진행 |
| 일관성(Coherence) | 답변 내에서 앞뒤가 맞는지. "서울은 수도이다"라고 하고 "부산이 수도이다"라고 하면 일관성 없음 |
| 논리성(Logical) | 논리적 추론이 올바른지. "A이면 B, B이면 C, 따라서 A이면 C" |
| 후처리(Post-processing) | LLM 출력을 가공하는 추가 작업. 요약, 형식 변환, 필터링 등 |
핵심 요약
"평가할 수 없는 건 성과가 아니다." AI 앱 평가는 생성 능력(일관성/논리성/할루시네이션), 지시 수행 능력(이해→수행, 멀티턴), 역할 수행(SFT 학습 의존)으로 나뉜다.
Java 비유: 코드 리뷰에서 "잘 돌아가는 것 같아요"는 평가가 아님. JUnit 테스트 + SonarQube + 성능 측정이 있어야 진짜 품질 평가. AI도 마찬가지로 정량적 평가 체계가 반드시 필요.
딥다이브
생성 능력 평가 항목
| 구분 | 항목 | 설명 | 쉬운 비유 |
|---|---|---|---|
| 일반 | 일관성, 통일성, 논리성, 간결성 | 기본 품질 | 코드의 가독성, 네이밍 일관성 |
| 가치 | 창의성, 감성, 공격성, 의도 | 도메인 특화 | 사용자 경험(UX) 품질 |
| 분량 | 출력량 | 많을수록 요약 등 후처리 가능, 단 헛소리도 증가 | 로그가 많으면 디버깅 쉽지만 노이즈도 증가 |
| 할루시네이션 | 사실과 다른 내용 생성 | 사후 학습으로 줄임 | 런타임 버그. 겉보기에 정상이지만 결과가 잘못됨 |
지시 수행 능력
이해 → 수행 (2단계)
│
├── 컨텍스트: 문화/상황에 따라 의미 변화 (검지 = 1 vs 욕)
│ → "Java"가 프로그래밍 언어인지 커피인지 맥락으로 판단해야 하는 것과 같음
│
├── 멀티턴: 여러 턴에 걸친 지시 수행 ("신문지 가져와, 그리고 접어")
│ → "1번 API 호출 → 결과로 2번 API 호출"처럼 순차적 작업
│ → 이전 턴의 결과를 기억하고 다음 턴에 활용해야 함
│
└── 역할 수행: SFT 인스트럭션 학습 없으면 역할 부여 무의미
→ @Component로 빈 등록을 안 하면 @Autowired가 안 되는 것과 같음
실무 체크포인트
- [ ] 출력량이 많은 모델을 선택하여 후처리(요약) 가능성을 확보했는가?
- [ ] 멀티턴 지시 수행 능력을 테스트했는가?
- [ ] 도메인 맥락에서 용어가 올바르게 해석되는지 확인했는가?
EP13. AI 애플리케이션 평가 2
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 에이전틱 AI | AI가 스스로 판단하고 도구를 사용하여 작업을 수행하는 패러다임 | 배치 Job이 스스로 판단하며 여러 서비스를 호출하는 것 |
| SSE (Server-Sent Events) | 서버가 클라이언트에게 데이터를 실시간으로 스트리밍 전송하는 프로토콜 | SseEmitter로 실시간 데이터 전송. WebSocket의 단방향 버전 |
| LangSmith | LangChain에서 만든 LLM 파이프라인 모니터링/평가 도구 | Spring Actuator + Zipkin 같은 모니터링 도구 |
| RAGAS | RAG 시스템 전용 평가 프레임워크 | JUnit + Mockito로 RAG 파이프라인을 테스트하는 도구 |
| 파이프라인 | 데이터가 여러 단계를 거쳐 처리되는 구조 | Stream.of(data).map().filter().collect() 체인과 같은 구조 |
핵심 요약
도메인 평가가 진짜 돈 버는 핵심이다. 평가 시스템을 반드시 자동화해야 하며, 파이프라인 각 단계를 개별 평가해야 어떤 단계가 기여했는지 파악 가능하다.
딥다이브
에이전틱 AI vs 모델 발전의 순환
에이전트로 성능 향상 → 모델 회사가 기능 흡수 → 새 에이전트 구현 → 반복
"함부로 에이전틱 AI가 대세라 말할 수 없다"
비유: 써드파티 라이브러리가 유용한 기능 만듦 → Java/Spring이 해당 기능을 흡수 (예: Lombok → Java records, 외부 JSON 라이브러리 → Jackson 내장) → 써드파티가 또 새로운 기능을 만듦 → 반복
속도 문제: LLM 서비스의 근본적 느림
MySQL: 0.003초 vs ChatGPT: 30초 (10,000배 차이!)
보완 전략:
1. 스트리밍 출력 (SSE) — 토큰 단위 실시간 출력
→ Spring: SseEmitter로 구현. 전체 답변 대기 대신 한 글자씩 표시
2. 대기 중 애니메이션/추가 콘텐츠 (RPG 다운로드 미니게임처럼)
→ "분석 중입니다..." + 관련 팁 표시
3. 미국 공항 수하물 전략: 30분 걷게 설계 → 대기 불만 해소
→ 실제 시간은 줄이지 못하지만 체감 대기 시간을 줄이는 UX 설계
파이프라인 단계별 평가
[스플릿] → [파서] → [청킹] → [임베딩] → [프롬프트] → [LLM] → [출력]
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
개별 개별 개별 개별 개별
평가 평가 평가 평가 평가
→ 최종 결과만 보면 어떤 단계가 기여했는지 알 수 없음
→ LangSmith + RAGAS로 자동화
Java 비유: Microservice에서 장애가 발생하면 Zipkin/Jaeger로 각 서비스별 응답 시간과 에러를 추적하듯, AI 파이프라인도 각 단계별 품질을 추적해야 함. 최종 API 응답만 보고 "느리네"라고 하면 어느 서비스가 문제인지 모르는 것과 같음.
실무 체크포인트
- [ ] 평가 시스템을 자동화했는가? (수동 평가 = 평가 안 하겠다)
- [ ] 파이프라인 각 단계별 개별 평가 기준을 두고 있는가?
- [ ] LLM 응답 시간이 길 때 스트리밍(SSE)을 적용했는가?
EP14. AI 앱용 모델 선택
먼저 알아야 할 개념
| 용어 | 쉬운 설명 |
|---|---|
| 파일 API | PDF 등 파일을 모델 API에 올리면 자동으로 텍스트 추출/분할/검색(RAG)까지 해주는 기능 |
| 에이전트 그래프 | 에이전트의 워크플로우를 비주얼로 설계하는 도구. 순서도처럼 흐름을 정의 |
| 샌드박스 | 격리된 실행 환경. LLM이 생성한 코드를 안전하게 실행할 수 있는 공간 |
| 리더보드 | 모델 성능 순위표. MMLU, HumanEval 등 벤치마크 기준 랭킹 |
핵심 요약
도메인 분야를 입력 범위 × 출력 범위 4분류(A/B/C/D)로 나누고, 모델 API의 부가 기능(파일 API, 에이전트 그래프, 샌드박스 등)을 고려한다. 리더보드는 참고용이며, 도메인 코퍼스 PPL이 가장 만만한 대안이다.
딥다이브
도메인 분야 4분류
| 분류 | 입력 | 출력 | 예시 | 난이도 | 쉬운 비유 |
|---|---|---|---|---|---|
| A | 범용 | 범용 | ChatGPT | 최고 | 아무 질문이나 받아서 아무 형태로 답 |
| B | 범용 | 제한 | Cursor (코딩) | 중간 | 아무 질문이든 "코드"로만 답 |
| C | 제한 | 제한 | X-ray 분석, 119 분류 | 최저 | X-ray 사진만 받아서 "정상/비정상"만 답 |
| D | 제한 | 범용 | - | 높음 | 특정 데이터로 자유 형식 답 |
핵심: 우리 서비스가 C 분류에 가까울수록 성공 확률이 높다. 입출력 범위가 좁으면 모델이 잘못 답할 여지가 줄어들기 때문.
⚠️ 최신 업데이트: 모델 API 기능 확장
| 기능 | OpenAI | 비고 | |
|---|---|---|---|
| 파일 API (자동 RAG) | ✅ | ✅ (최근 추가) | PDF 올리면 파서/스플릿/RAG 전부 불필요 |
| 에이전트 그래프 | ✅ | - | 비주얼 에이전트 |
| 인터프리터 샌드박스 | ✅ | - | 파이썬 코드 실행 |
| Responses API | ✅ | - | Chat Completions 대체, 캐시 40~80% 개선 |
에이전트 구현 회사의 위기: 모델 API가 대부분 기능을 제공하면서 "개발자들이 이런 거 구현한 걸로 먹고 살 게 없어진다"
Java 비유: Spring이 초기에는 XML 설정이 복잡해서 편의 라이브러리가 많았는데, Spring Boot가 나오면서 대부분의 편의 라이브러리가 불필요해진 것과 같은 상황.
실무 체크포인트
- [ ] 도메인을 A/B/C/D 중 어디에 해당하는지 분류했는가?
- [ ] 모델 API의 부가 기능(파일 API, RAG 내장)으로 자체 구현을 대체할 수 있는지 검토했는가?
- [ ] 입출력 범위를 좁혀 C 분류에 가깝게 설계할 수 있는지 검토했는가?
EP15. 모델 특성에 따른 프롬프트
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| Few-shot | 예시를 몇 개 보여주고 패턴을 학습시키는 프롬프트 기법 | 코드 예제를 3개 보여주고 "이런 패턴으로 코드 짜줘"라고 하는 것 |
| Zero-shot | 예시 없이 지시만으로 작업을 수행하게 하는 것 | 명세서만 주고 "이거 만들어"라고 하는 것 |
| ChatML | Chat Markup Language. system/user/assistant 구조의 대화 포맷 | JSON 형식의 대화 구조. {"role": "system", "content": "..."} |
| 라마(Llama) | Meta(Facebook)가 공개한 오픈소스 LLM 시리즈 | Spring의 오픈소스 버전 같은 것. 무료로 쓸 수 있는 대형 모델 |
| 프롬프트 편향 | 프롬프트의 내용/위치가 모델 출력에 미치는 체계적 영향 | application.yml의 설정이 앱 동작을 결정하듯, 프롬프트가 AI 동작을 결정 |
| Responses API | OpenAI의 차세대 API. 기존 Chat Completions을 대체. 4개 역할 지원 | REST API v2. 기존 v1보다 구조가 세분화되고 캐시 효율이 높아진 버전 |
핵심 요약
프롬프트 효과는 모델의 SFT 학습 구조에 의존한다. 라마 계열은 시스템에 간단히, ChatML 계열(GPT/Claude)은 시스템에 적극 기술한다. Few-shot은 절대 시스템 프롬프트에 넣지 말고 user-assistant 턴으로 기술한다.
딥다이브
라마 계열 vs ChatML 계열 SFT 구조
| 구분 | 라마 계열 | ChatML 계열 (GPT/Claude/Gemini) |
|---|---|---|
| SFT 구조 | instruction + user → assistant (단일) | system + user → assistant (멀티턴) |
| 시스템 프롬프트 | 간단하게 (역할/상황만) | 적극적으로 (지침/제약/형식) |
| 시스템에 많이 넣으면 | 오작동 | 강력한 편향 효과 |
실무 핵심: GPT/Claude/Gemini를 쓴다면 시스템 프롬프트에 상세한 지침을 넣어라. Llama/Mistral 등 오픈소스를 쓴다면 시스템은 간단하게, 지침은 user 메시지에 넣어라. 모델이 다르면 프롬프트 전략도 달라야 한다!
시스템 프롬프트가 강력한 2가지 이유
1. SFT 학습 구조: 시스템을 지침으로 삼도록 학습됨
→ application.yml이 앱 동작을 결정하듯, system 프롬프트가 모델 동작을 결정
2. 어텐션 구조: 앞쪽 토큰이 모든 후속 토큰에 영향 발산
→ 첫 토큰이 5,000번째까지 5,000번 영향
→ 비유: 회의 시작 때 "오늘 목표는 X입니다"라고 하면 전체 회의에 영향
단, 실제 더 강한 영향력은 마지막 토큰 쪽
→ 뒤쪽 토큰이 다음 토큰 생성에 직접 영향
→ 롱 컨텍스트에서는 유저 프롬프트 뒤에 강하게 밀어넣는 방법도 유효
Few-shot은 반드시 턴으로
| 위치 | 효과 | 이유 |
|---|---|---|
| ❌ 시스템 프롬프트에 샷 | 지침으로 인식 → 같은 질문에 동일 답변 고착화 | 시스템=규칙이므로 예시를 "반드시 따라야 할 규칙"으로 인식 |
| ✅ user-assistant 턴으로 | 정상적 퓨샷 학습 효과 | 대화 맥락에서 "이런 패턴이구나"라고 학습 |
❌ 잘못된 방법:
system: "Q: 서울의 수도는? A: 서울은 한국의 수도입니다. ..."
user: "부산은 뭐야?"
→ 모델이 "부산은 한국의 수도입니다"라고 답할 수 있음 (패턴 고착화)
✅ 올바른 방법:
system: "너는 한국 지리 전문가야"
user: "서울의 수도는?"
assistant: "서울은 한국의 수도입니다"
user: "부산은 뭐야?"
→ 모델이 대화 맥락에서 자연스럽게 학습
⚠️ 최신 업데이트: OpenAI Responses API
기존 Chat Completions: system / user / assistant (3롤)
Responses API: instruction / developer / user / assistant (4롤)
instruction: 짧은 역할 + 배경 → "너는 한국 지리 전문가야" (변하지 않는 부분)
developer: 상세 지침 → "답변은 3문장 이내로..." (변할 수 있는 규칙)
→ 변하지 않는 부분(instruction)을 분리하면 캐시 재활용 극대화!
성능: SWE-bench 3% 개선, 캐시 40~80% 향상
실무 체크포인트
- [ ] 사용 중인 모델의 SFT 학습 구조(라마 vs ChatML)를 파악했는가?
- [ ] Few-shot을 시스템이 아닌 user-assistant 턴으로 기술하고 있는가?
- [ ] Chat Completions → Responses API 전환을 검토했는가?
EP16. 고급 프롬프트 관리
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 프롬프트 템플릿 | 사용자 질의를 모델 친화적 입력으로 감싸는 틀 | Thymeleaf 템플릿. "${user_query}"를 포함한 미리 정의된 프롬프트 |
| 컨텍스트 엔지니어링 | 모델에 제공하는 주변 정보(문서, 스키마, 예시)를 설계하는 기술 | API 호출 시 request body를 어떻게 구성할지 설계하는 것 |
| MCP (Model Context Protocol) | AI 모델이 외부 도구/데이터에 접근하기 위한 표준 프로토콜 | JDBC가 DB 연결 표준이듯, MCP는 AI-도구 연결 표준 |
| 프롬프트 인젝션 | 악의적 사용자가 프롬프트를 조작하여 모델을 오용하는 공격 | SQL Injection과 같은 원리. 입력을 통해 시스템을 조작 |
| 프롬프트 버전 관리 | 프롬프트를 버전별로 관리하고 성능을 비교하는 것 | Git으로 설정 파일을 버전 관리하는 것과 같음 |
핵심 요약
프롬프트 템플릿은 사용자 질의를 모델 친화적 입력의 "일부"로 만드는 틀이다. LLM에게 프롬프트 수정을 시키면 어텐션 편향에 최적화된 결과를 얻을 수 있다. 프롬프트 보안은 다중 게이트 패턴으로 구축한다.
딥다이브
⚠️ 최신 업데이트: 컨텍스트 엔지니어링 (2026)
2026년, 프롬프트 엔지니어링은 컨텍스트 엔지니어링으로 진화했다. "어떻게 질문하느냐"보다 "어떤 정보를 둘러싸느냐"가 모델 성공을 결정한다.
프롬프트 엔지니어링: 질문을 잘 쓰는 기술 (how you ask)
→ 비유: SQL 쿼리를 잘 작성하는 것
컨텍스트 엔지니어링: 질문 주변 정보를 설계하는 기술 (what surrounds your request)
→ 비유: DB 스키마, 인덱스, 캐시를 잘 설계하는 것
→ 스키마, 파일, 데이터 형식, 검색 아키텍처가 성패를 결정
핵심 전환: "좋은 질문"보다 "좋은 맥락"이 더 중요해졌다. 마치 좋은 SQL 쿼리보다 좋은 DB 설계가 더 중요하듯.
MCP(Model Context Protocol)는 Linux Foundation 산하 Agentic AI Foundation이 관리하며, 월간 SDK 다운로드 9,700만+ 회를 기록. Anthropic, OpenAI, Google, Microsoft가 채택한 보편 표준이다.
MCP = AI 세계의 JDBC: DB마다 다른 드라이버를 JDBC가 통합했듯, 도구마다 다른 연결 방식을 MCP가 통합. 한 번 구현하면 모든 AI 모델에서 사용 가능.
프롬프트 보안: 다중 게이트 패턴
[입력] → 정규식/키워드 필터 ← Spring Security의 필터 체인과 같은 구조!
→ LLM 입력 검사 ← AI가 "이 입력이 악의적인가?" 판단
→ 보안 프롬프트 감싸기 ← "어떤 요청이든 이 규칙을 지켜라" 강제
→ [LLM 실행]
→ LLM 출력 검사 ← 출력에 민감 정보가 없는지 확인
→ 멀티턴 감사 ← 대화 길어지면 보안 약화 → 주기적 재검사
Java 비유: Spring Security의
FilterChain과 동일한 패턴.OncePerRequestFilter→AuthenticationFilter→AuthorizationFilter→ 비즈니스 로직 AI에서도 입력 필터 → 검사 → 실행 → 출력 검사의 체인 구조.
프롬프트 버전 관리
평가 데이터셋(30개+) + 평가 모델
→ 프롬프트 v1: 72점
→ 프롬프트 v2: 78점
→ 프롬프트 v3: 81점
→ 루프: LLM에게 프롬프트 개선 요청 → 재평가 → 반복
왜 LLM에게 프롬프트 개선을 시키는가? LLM은 자신의 어텐션 메커니즘을 "체감"하므로 어떤 토큰 배치가 좋은 출력으로 이끄는지 사람보다 더 잘 안다. 마치 JVM 전문가보다 JVM 자체가 GC 최적화를 더 잘 하는 것과 비슷.
실무 체크포인트
- [ ] 프롬프트를 LLM에게 개선시키고 있는가? (사람보다 어텐션 편향 최적화에 유리)
- [ ] 다중 게이트 보안 패턴을 적용했는가? (프롬프트 인젝션 방어)
- [ ] 프롬프트 버전을 평가 데이터셋으로 점수화하여 관리하고 있는가?
EP17. 컨텍스트 증강과 RAG
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| RAG (Retrieval-Augmented Generation) | 외부 문서를 검색하여 LLM에 입력으로 제공, 정확한 답변을 유도하는 기법 | DB에서 관련 데이터를 SELECT하여 비즈니스 로직에 전달하는 것 |
| 컨텍스트 윈도우 | 모델이 한 번에 처리할 수 있는 최대 토큰 수 (128K, 200K 등) | StringBuilder의 최대 용량. 초과하면 앞부분이 잘림 |
| 청킹(Chunking) | 긴 문서를 작은 조각으로 나누는 것. RAG의 전처리 단계 | 큰 파일을 적절한 크기로 분할하여 처리하는 것. BufferedReader로 chunk 단위 읽기 |
| 임베딩 모델 | 텍스트를 숫자 벡터로 변환하는 전용 모델. 의미가 비슷한 텍스트는 비슷한 벡터 | hashCode()의 의미론적 버전. 비슷한 것은 비슷한 벡터를 가짐 |
| 코사인 유사도 | 두 벡터가 같은 방향을 가리키는 정도. 1=동일, 0=무관, -1=반대 | 두 배열의 "방향" 비교. cos(θ) 값으로 유사도 측정 |
| 리랭커(Reranker) | 검색 결과를 다시 정렬하여 가장 관련 있는 것을 상위로 올리는 모델 | ORDER BY 절을 LLM이 동적으로 결정하는 것 |
| 벡터 DB | 벡터(숫자 배열)를 저장하고 유사한 벡터를 빠르게 검색하는 DB | Redis + 유사도 검색 기능. Pinecone, Milvus, ChromaDB 등 |
핵심 요약
컨텍스트 엔지니어링은 모델 입력 컨텍스트 예산을 질의/프롬프트/배경 정보/메모리/도구 정보에 배분하는 것이다. RAG의 엄밀한 정의는 임베딩 모델 + 코사인 유사도 검색이며, 청킹이 RAG 품질의 핵심이다.
딥다이브
컨텍스트 예산 배분
[모델 컨텍스트 윈도우] (예: 128K 토큰)
├── 시스템 프롬프트 (지침/역할) → ~2K 토큰
├── 배경 정보 (RAG 검색 결과) → ~10~30K 토큰
├── 대화 기록 (메모리) → ~5~20K 토큰
├── 도구 설명 (MCP 서버 200개면 70K 소비!) → 가변
└── 사용자 질의 → ~1K 토큰
→ 도구가 많으면 메모리/배경 정보 입력 불가
→ 컨텍스트 예산 관리가 핵심
Java 비유: JVM 힙 메모리 예산과 같다. - 힙 = 컨텍스트 윈도우 (총 용량) - 스택 = 시스템 프롬프트 (고정 할당) - 오브젝트 풀 = RAG 결과 (필요한 만큼 할당) - GC 대상 = 오래된 대화 기록 (필요시 정리) 도구 설명이 너무 많으면 OOM(Out of Memory)처럼 컨텍스트 초과!
RAG 작동 원리 (전체 흐름)
1. 사전 준비 (오프라인):
문서 → 청킹 → 임베딩 모델 → 벡터 DB에 저장
2. 질의 시 (온라인):
사용자 질의 → 임베딩 모델 → 벡터로 변환
→ 벡터 DB에서 코사인 유사도 검색
→ 상위 K개 청크 반환
→ 시스템 프롬프트 + 검색 결과 + 사용자 질의 → LLM → 답변
Java 비유: ElasticSearch의 AI 버전이라고 생각하면 됨. ES가 키워드로 검색하듯, 벡터 DB는 "의미"로 검색. "자동차 보험"을 검색하면 "차량 보장"도 찾아주는 것이 벡터 검색.
RAG 강화 옵션
| 옵션 | 설명 | 쉬운 비유 |
|---|---|---|
| 리랭커 | 검색 결과를 LLM으로 재정렬 | Google 검색 결과를 AI가 한번 더 정렬 |
| 본문+임베딩 결합 | 키워드 일치 + 의미론 검색 = 사용자 선호도 최고 | SQL LIKE + 벡터 검색 결합 |
| 사용자 질의 재작성 | LLM이 질의를 검색에 적합한 형태로 개선 | "이거 어떻게 해?" → "Spring Boot에서 REST API 만드는 방법" |
| 멀티벡터 스토어 | 하나의 본문에 여러 임베딩 | 한 클래스에 여러 인덱스 키를 생성하는 것 |
청킹이 RAG 품질의 핵심
청크 크기: 임베딩 모델 카드에서 최적 길이 확인 (고민 불필요)
핵심: 청크 하나가 "완결된 의미론"을 갖고 있는지
나쁜 청킹: "Spring Security는 인증과" / "인가를 처리하는 프레임워크이다"
→ 첫 번째 청크만으로는 의미 파악 불가
좋은 청킹: "Spring Security는 인증과 인가를 처리하는 프레임워크이다"
→ 하나의 청크가 완결된 의미를 가짐
다차원 청킹 기법:
- 분할 임베딩: 긴 문서를 나눠 각각 임베딩
- 점진적 묶음: 문장 → 단락 → 섹션으로 묶어 임베딩
- 시제 기반 그룹: 백설공주 소설의 시간대별 분리
- 멀티모달: 이미지 청크, 사운드 스펙트럼 청크
실무 체크포인트
- [ ] 컨텍스트 예산에서 도구 설명이 차지하는 비중을 관리하고 있는가?
- [ ] 키워드 검색(본문) + 임베딩 검색(의미론)을 결합하고 있는가?
- [ ] 청크가 완결된 의미론을 갖는지 검증했는가?
- [ ] 벡터 DB를 선택했는가? (Pinecone/Milvus/ChromaDB/pgvector 등)
EP18. AI 에이전트와 도구
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 에이전트(Agent) | LLM이 스스로 판단하여 도구를 호출하고 결과를 분석하여 다음 행동을 결정하는 자율 시스템 | Spring Batch Job + 동적 Step. 어떤 Step을 실행할지 AI가 런타임에 결정 |
| 도구(Tool) | 에이전트가 사용할 수 있는 기능. 검색, API 호출, 코드 실행 등 | @Service 빈들. 에이전트가 필요한 서비스를 골라서 호출 |
| Tool Use (Function Calling) | LLM이 "이 도구를 호출해야 합니다"라고 응답하면 앱이 실행하는 패턴 | @FeignClient 호출을 AI가 결정하는 것 |
| R&R (Roles & Responsibilities) | 각 도구의 역할과 책임 범위를 명확히 정의하는 것 | 서비스 간 책임 분리 (SRP). 각 서비스가 하나의 역할만 담당 |
| n8n | 코드 없이 에이전트 워크플로우를 비주얼로 구축하는 도구 | Jenkins 파이프라인 UI처럼 드래그&드롭으로 워크플로우 구성 |
핵심 요약
에이전틱 AI의 핵심은 메모리이다. 도구 사용(Tool Use)은 LLM이 도구 호출 여부를 스스로 결정하고, 만족할 때까지 반복하는 구조다. 도구가 많으면 서브 프롬프트로 분할한다.
딥다이브
에이전트 메모리 계층
[세션 메모리] 현재 대화 이력 → HttpSession
[사용자 컨텍스트] 사용자 프로필, 선호도 → UserProfile DB
[앱 지침] "아메리칸 항공 사용 금지" → application.yml 설정
[외부 DB / RAG] 검색 결과 → ElasticSearch/Redis
[도구 결과] 도구 실행 결과 → API 응답 캐시
Java 비유: Spring 앱의 데이터 계층과 정확히 대응. 세션=HttpSession, 설정=properties, 외부=DB, 캐시=Redis. 에이전트가 효과적으로 동작하려면 이 모든 계층의 데이터에 접근 가능해야 함.
도구 사용(Tool Use) 메커니즘
사용자 질의 → LLM 판단 → "도구 X 호출 필요" (JSON 응답)
│
앱이 도구 X 실행 ← 여기가 개발자가 구현하는 부분!
│
결과를 LLM에 재입력
│
LLM 판단 → 만족? → 최종 답변
└→ 불만족 → 다른 도구 호출 → 반복
Java 비유: Strategy 패턴 + Chain of Responsibility 패턴의 조합. LLM이 Strategy를 선택하고(어떤 도구를 쓸지), 결과에 따라 다음 Chain을 결정.
java // LLM이 이런 판단을 AI로 자동 수행: if (질의.contains("날씨")) return toolService.getWeather(args); else if (질의.contains("주가")) return toolService.getStock(args); // 단, AI가 하므로 "날씨가 어떤가요"뿐 아니라 "비 올까?"도 인식
도구 사용 주의점
| 주의 | 설명 | 쉬운 비유 |
|---|---|---|
| 웹 검색 제공 시 | 다른 전용 도구가 무력화되는 경향 | Google에 다 물어볼 수 있으면 사전을 안 펴는 것 |
| 도구 수 | 200개면 서브 프롬프트 분할 (각 10개씩 배분) | 메뉴가 200개인 식당은 주문이 어려움. 카테고리로 분류 필요 |
| R&R | 도구 간 기능 겹침 방지 | @Service가 중복 기능을 가지면 혼란 |
| 인자/응답 | 단순한 프리미티브가 좋음 (복잡한 JSON은 실효성 저하) | 메서드 파라미터는 단순할수록 호출 실수가 적음 |
| 설명 | LLM 친화적으로 작성 (퓨샷 포함 가능) | Javadoc처럼 도구의 용도/예시를 명확히 기술 |
n8n: 에이전틱 AI 비주얼 빌더 분야의 "시장 제패자". AWS ECS Docker에서 운영 가능.
실무 체크포인트
- [ ] 에이전트 메모리 계층(세션/사용자/지침/외부DB)을 설계했는가?
- [ ] 웹 검색 도구가 전용 도구를 무력화하지 않도록 도구 구성을 조정했는가?
- [ ] 도구의 인자/응답을 단순한 프리미티브로 설계했는가?
- [ ] 도구 설명에 "언제 이 도구를 사용하는지" 퓨샷 예시를 포함했는가?
EP19. 파인 튜닝과 LoRA
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 파인 튜닝(Fine-Tuning) | 사전학습된 모델을 특정 도메인/용도에 맞게 추가 학습하는 것 | 프레임워크를 커스터마이징하는 것. Spring 기본 설정을 프로젝트에 맞게 변경 |
| 파멸적 망각 | 파인튜닝하면 새 도메인을 배우면서 기존 능력을 잃는 현상 | 특정 모듈을 수정하다 다른 모듈이 깨지는 것. 사이드 이펙트 |
| LoRA (Low-Rank Adaptation) | 모델 전체를 수정하지 않고 작은 어댑터만 추가하여 학습. PEFT의 대표 기법 | AOP(Aspect) 패턴. 원본 코드를 건드리지 않고 Aspect만 추가하여 동작 변경 |
| PEFT | Parameter-Efficient Fine-Tuning. 전체 파라미터 중 극소수만 학습하는 기법 | 1만 줄 코드 중 10줄만 수정하여 동작을 바꾸는 것 |
| 어댑터(Adapter) | LoRA에서 추가하는 작은 행렬. 학습 후 원본에 병합 가능 | @Around 어드바이스. 실행 후 원본 메서드에 병합 가능 |
| 저랭크 분해 | 큰 행렬을 작은 행렬 2개의 곱으로 표현하여 파라미터 수를 줄이는 수학 기법 | 10x10 행렬(100개)을 10x2 + 2x10(40개)으로 분해. 60% 절감 |
핵심 요약
파인 튜닝의 최대 장점은 인퍼런스 비용 절감이며, 최대 위험은 파멸적 망각이다. LoRA는 어텐션 가중치에 저랭크 어댑터를 삽입하여 효율적으로 학습하는 현재 PEFT의 승자다.
딥다이브
파인 튜닝 장단점
| 장점 | 단점 | 쉬운 비유 |
|---|---|---|
| 인퍼런스 비용 절감 (가장 큼) | 파멸적 망각 (기존 밸런스 붕괴) | 전문화하면 효율적이지만 범용성을 잃음 |
| 프롬프트 기술 불필요 | 재평가 비용 막대 | 코드를 수정하면 전체 테스트를 다시 돌려야 함 |
| 톤앤매너 통제 | 학습 비용 과다 ("파멸적 비용") | GPU 수백만원 + 데이터 준비 시간 |
| 고객 피드백(DPO) 직접 반영 | 범용 모델 신버전에 의한 무효화 | Spring 5용 커스텀 코드가 Spring 6에서 안 돌아가는 것 |
파인 튜닝 vs 프롬프트 엔지니어링 판단 기준: - 프롬프트로 해결 가능하면 → 프롬프트 사용 (비용 저렴, 빠름) - 프롬프트로 안 되고 + 충분한 데이터 있으면 → 파인 튜닝 고려 - 인퍼런스 비용이 월 수백만원 이상이면 → 파인 튜닝으로 비용 절감 효과 큼
LoRA (Low-Rank Adaptation) — 저랭크 적응
기존 행렬: W (10×10 = 100 파라미터)
LoRA: A(10×k) × B(k×10) = 저랭크 분해
k=1: 10+10 = 20 파라미터 (80% 절감!)
k=2: 20+20 = 40 파라미터 (60% 절감)
기존 파라미터는 건드리지 않고 어댑터만 추가 (freeze + adapter)
→ 학습 완료 후 어댑터를 원본에 병합하여 인퍼런스 비용 제거
Java AOP 비유:
원본 클래스(freeze) + @Around 어드바이스(LoRA 어댑터) ↓ 학습 완료 후 원본에 병합 (인라인화)원본 코드는 건드리지 않고, Aspect만 추가하여 동작을 바꿈. 배포 시에는 Aspect를 원본에 병합하여 성능 오버헤드 제거.
LoRA 적용 전략
| 전략 | 대상 레이어 | 비용 | 효과 | 언제 사용? |
|---|---|---|---|---|
| 기본 (권장) | K/Q/V/O + gate/up/down 전부 | 높음 | 최고 | 충분한 GPU가 있을 때 |
| 비용 절감 A | 후방 레이어 위주 | 중간 | 좋음 | GPU 메모리 부족 시 |
| 비용 절감 B | Q/V만 | 낮음 | 지식 학습 위주 | 최소 비용으로 시도할 때 |
실무 체크포인트
- [ ] 파인 튜닝 후 기존 평가 + 튜닝 부분 평가를 모두 재수행했는가?
- [ ] LoRA 기본 설정(모든 레이어 K/Q/V/O + gate/up/down)으로 시작했는가?
- [ ] 학습 완료 후 어댑터 병합으로 인퍼런스 비용을 제거했는가?
- [ ] 프롬프트 엔지니어링으로 먼저 해결을 시도한 후 파인 튜닝을 결정했는가?
EP20. 모델을 진짜로 학습시키고 운영하기
먼저 알아야 할 개념
| 용어 | 쉬운 설명 | Java 비유 |
|---|---|---|
| 라마 팩토리 | 웹 UI로 코드 없이 모델을 튜닝할 수 있는 설치형 도구 | Spring Initializr의 AI 버전. 클릭으로 모델 튜닝 |
| vLLM | 고성능 LLM 서빙 엔진. 프로덕션 환경에서 모델을 효율적으로 운영 | Tomcat/Netty 같은 서버 엔진. 대규모 트래픽 처리에 최적화 |
| PagedAttention | OS의 가상 메모리 페이징처럼 KV 캐시를 관리하는 vLLM의 핵심 기술 | JVM의 GC처럼 메모리를 효율적으로 관리. 메모리 낭비 최소화 |
| 지식 증류(Distillation) | 큰 모델(선생)의 지식을 작은 모델(학생)에 전달하는 기법 | 시니어 개발자가 주니어에게 노하우를 전수하는 것 |
| 합성 데이터 | AI가 생성한 학습용 데이터. 선생 모델이 만든 질문-답변 쌍 | Mock 데이터 자동 생성. 테스트 데이터를 프로그램으로 생성하는 것 |
| 리즈닝 모델 | 답변 전에 사고 과정을 거치는 모델. <think> 태그로 추론 과정 표시 |
디버그 로그를 남기는 코드. 결과뿐 아니라 과정도 보여줌 |
| 프리픽스 캐시 | 여러 요청에서 공통되는 앞부분(시스템 프롬프트 등)의 KV 캐시를 공유 | static final 상수처럼 공통 부분을 미리 계산해두고 재사용 |
핵심 요약
"학습은 특별하지 않다. 데이터가 특별하다." 라마 팩토리가 설치형 튜닝 도구 최강이며, vLLM이 프로덕션 인퍼런스 엔진 필수다. 인퍼런스 비용 절감 1순위는 UI로 인퍼런스 호출 자체를 줄이는 것이다.
핵심 마인드셋: 학습 도구는 누구나 쓸 수 있다 (라마 팩토리 = 공개 도구). 차별화는 고품질 도메인 데이터 확보에서 나온다. 좋은 프레임워크보다 좋은 데이터가 더 중요한 세계.
딥다이브
SFT 데이터 구조 (ChatML)
// 도구 사용 학습 데이터 — Spring 개발자에게 익숙한 JSON 구조
{ "role": "system", "content": "인스트럭션 + 도구 정의" } // application.yml
{ "role": "user", "content": "서울 날씨 알려줘" } // HTTP Request
{ "role": "assistant", "tool_use": { "name": "get_weather", "args": {"city": "서울"} } } // @FeignClient 호출
{ "role": "tool", "content": "서울 14도, 맑음" } // 외부 API 응답
{ "role": "assistant", "content": "서울은 현재 14도이며 맑습니다." } // HTTP Response
이 JSON 구조로 SFT 학습하면 모델이 도구 사용 패턴을 학습한다. "어떤 질문에 어떤 도구를 호출할지"를 데이터로 가르치는 것.
리즈닝 모델 학습
어시스턴트 응답에 <think> 태그로 사고 과정 포함:
<think>1단계: 질문 분석... 2단계: 관련 지식 검색...</think>
최종 답변: ...
→ 이 형식의 데이터로 SFT 학습하면 리즈닝 모델이 됨!
→ 비유: log.debug()가 포함된 코드로 학습시키면 디버그 로그를 남기는 모델이 됨
지식 증류 (Distillation)
큰 모델(선생, 예: GPT-4) → 작은 모델(학생, 예: Llama-7B)
진정한 증류: 선생의 전체 보캐블러리 로짓을 학생에게 학습
문제: 보캐블러리 불일치, 임베딩 차원 불일치, 비용 과다
비유: 선생의 모든 사고방식을 학생에게 전이 (비현실적)
현실적 증류: 선생이 만든 합성 데이터로 학생을 SFT
장점: 간단, 보캐블러리 불일치 문제 없음
핵심: 같은 패밀리 모델 간(큰→작은) 증류가 가장 효과적
비유: 선생이 쓴 교과서를 학생이 공부 (가능!)
튜닝 도구 비교
| 도구 | 유형 | 특징 | 쉬운 비유 |
|---|---|---|---|
| 라마 팩토리 | 설치형 | 최강. 웹 UI, 코드 불필요, 메타팀 프리셋, 도커 설치 | IntelliJ IDEA의 AI 튜닝 버전 |
| H2O LLM Studio | 설치형 | - | VSCode 수준 |
| 허깅페이스 AutoTrain | 서비스형 | 클릭 몇 번으로 튜닝 | GitHub Actions (클라우드) |
⚠️ 최신 업데이트: vLLM 인퍼런스 엔진
vLLM은 PagedAttention으로 HuggingFace Transformers 대비 최대 24배 처리량을 달성한다. 주요 기능:
- PagedAttention: OS 가상 메모리 페이징 방식으로 KV 캐시 관리
- 비유: JVM G1GC처럼 메모리를 블록 단위로 관리하여 파편화 방지
- Automatic Prefix Caching: 공유 시스템 프롬프트의 KV 캐시 재활용 → RAG/멀티턴에 유리
- 비유: @Cacheable로 공통 계산 결과를 캐시
- Chunked Prefill: 긴 프롬프트를 분할하여 다른 요청 처리 허용
- 비유: 비동기 처리로 하나의 큰 요청이 다른 요청을 블로킹하지 않음
- NVIDIA, AMD, Intel, TPU 등 다양한 하드웨어 지원
인퍼런스 비용 절감 전략 (우선순위)
1. UI로 해결 (가장 효과적) — 벡터 DB 검색 결과를 사이드바에 표시
→ 사용자가 클릭으로 해결, 인퍼런스 호출 자체를 줄임
→ 비유: DB 조회만으로 해결되면 비싼 외부 API를 안 부르는 것
2. 벡터 DB 캐시 — 유사도 0.97+ 이면 LLM 없이 검색 결과 직접 제시
→ 비유: Redis 캐시 히트. DB까지 안 가도 됨
3. vLLM — 파이프라이닝으로 100개 요청이 20~30초
→ 비유: Connection Pool + 비동기 처리
4. 양자화 — FP16 → INT8/FP8
5. KV 캐시 — 이전 토큰 재활용
6. Flash Attention — SRAM 직접 계산
7. 프리픽스 캐시 — 연속 요청의 앞부분 동일 시 KV 캐시 재활용
올라마/LM Studio는 "범용 장난감". 프로덕션에서는 vLLM 필수. 비유: 개발용 H2 DB vs 프로덕션용 PostgreSQL. 테스트에는 Ollama, 운영에는 vLLM.
실무 체크포인트
- [ ] 라마 팩토리로 LoRA 튜닝을 실행해봤는가?
- [ ] 프로덕션에서 올라마 대신 vLLM을 사용하고 있는가?
- [ ] UI 기반 인퍼런스 절감 전략을 적용했는가?
- [ ] 고품질 도메인 데이터를 확보하는 전략(합성 데이터, 전문가 레이블링)을 수립했는가?
부록 A. 용어 사전
Spring/Java 개발자가 이해하기 쉽도록 각 용어에 Java 비유를 함께 정리했습니다.
| 용어 | 정의 | Java/Spring 비유 |
|---|---|---|
| AI 엔지니어링 | AI가 서비스 핵심(30%+)인 서비스를 체계적으로 만드는 방법론. ML 연구가 아닌 서비스 구축 관점 | Spring Boot로 서비스를 만드는 것처럼, AI 모델을 서비스로 만드는 엔지니어링 |
| MoE | Mixture of Experts. 전체 FFN 중 일부 전문가만 활성화하여 효율적으로 추론. 게이트 네트워크가 입력별로 2~8개 전문가를 선택 | @Conditional 빈 로딩. 전체 빈 중 조건에 맞는 것만 활성화하여 메모리 절약 |
| Flash Attention | GPU SRAM(캐시)에서 직접 어텐션 계산하여 HBM(메인 메모리) 이동 비용 제거. 타일링 기법으로 메모리 O(N²)→O(N) | L1 캐시에서 직접 계산 vs RAM 왕복. @Cacheable로 DB 왕복 없이 로컬 캐시에서 처리하는 것과 유사 |
| KV 캐시 | 이전 토큰의 Key/Value 텐서를 GPU 메모리에 저장하여 다음 토큰 생성 시 재활용. 없으면 매 토큰마다 전체 재계산 필요 | HashMap<이전토큰, 계산결과> 캐시. 같은 쿼리를 매번 DB에 보내지 않고 캐시에서 조회 |
| GQA | Grouped Query Attention. Q 헤드를 그룹으로 묶고 그룹마다 K/V를 공유. MHA(1:1)와 MQA(N:1)의 중간 | 여러 @Service가 하나의 @Repository를 공유. 각각 만들지 않고 그룹별로 공유하여 메모리 절감 |
| RoPE | Rotary Position Embedding. 토큰 위치를 벡터 회전각으로 인코딩. 상대적 위치 관계가 내적에 자연스럽게 반영 | 배열 인덱스 대신 각도로 위치 표현. Collections.rotate()처럼 회전하면 상대 위치가 보존 |
| LongRoPE | RoPE 확장 기법. 고주파(단거리)와 저주파(장거리) 차원을 분리하여 차등 스케일링. 128K+ 컨텍스트 지원 | 로컬 캐시(L1, 단거리)와 분산 캐시(Redis, 장거리)를 별도 전략으로 관리 |
| SSM/S4/맘바 | State Space Model 계열. 시퀀스를 시간적 상태 변수로 모델링하여 O(N) 선형 복잡도 달성. 트랜스포머의 O(N²) 한계 극복 | Stream.reduce() — 누적 상태로 처리. 전체를 메모리에 올리지 않고 하나씩 흘려보내며 상태 갱신 |
| 잠바(Jamba) | 맘바(선형 시퀀스) + 트랜스포머(정밀 어텐션) 하이브리드. 긴 문맥은 맘바, 핵심 구간은 어텐션으로 처리 | WebFlux(비동기 스트림) + @Transactional(정밀 처리) 혼합 아키텍처 |
| SFT | Supervised Fine-Tuning. (질문, 정답) 쌍 데이터로 모델의 출력 방향을 조정. 파인튜닝의 첫 단계 | application.yml 설정 오버라이드. 기본 동작은 유지하면서 특정 응답 패턴을 커스텀 |
| RLHF | Reinforcement Learning from Human Feedback. 인간 평가자가 매긴 선호도 점수를 보상 모델이 학습 → PPO로 최적화 | QA팀 피드백 기반 리팩터링. 인간 코드리뷰(보상) → SonarQube(보상 모델) → 자동 수정(PPO) |
| DPO | Direct Preference Optimization. 보상 모델 없이 (선택, 거부) 쌍의 로그 확률 차이를 직접 최적화. RLHF보다 간단하고 안정적 | A/B 테스트 결과로 바로 코드 수정. 별도 평가 시스템(보상 모델) 없이 직접 최적화 |
| PPO | Proximal Policy Optimization. 정책 업데이트 폭을 제한하여 학습 안정성 보장. RLHF의 핵심 알고리즘 | Rate Limiter. API 호출 속도를 제한하듯 모델 업데이트 폭을 제한하여 발산 방지 |
| 양자화 | 모델 가중치의 숫자 정밀도를 줄여(FP32→FP16→INT8→INT4) 메모리와 계산량 절감. 약간의 성능 손실과 트레이드오프 | double→float→int→short 타입 다운캐스팅. 정밀도를 줄이면 메모리는 절약되지만 오차 증가 |
| 할루시네이션 | LLM이 확률적 토큰 생성 과정에서 사실과 다른 내용을 자신감 있게 출력하는 현상. 구조적으로 완전 제거 불가 | NullPointerException처럼 구조적으로 발생. null 참조가 언어 설계의 한계이듯, 확률적 생성이 LLM의 한계 |
| PPL | Perplexity. 교차 엔트로피의 지수. 1에 가까울수록 예측 정확, 100 이상이면 거의 랜덤. 양자화 전후 품질 비교에 활용 | 단위 테스트 커버리지. 100%=완벽(PPL=1), 0%=랜덤(PPL=∞). 리팩터링 전후 커버리지 비교 |
| 로그 프로브 | 각 토큰이 생성될 확률의 자연로그 값. 0에 가까울수록 모델이 확신, -∞에 가까울수록 불확실 | log.getLevel(). DEBUG(-∞쪽)=불확실, INFO(0쪽)=확신. 확신도의 수치적 표현 |
| LLM-as-Judge | LLM을 채점관으로 사용하여 다른 LLM 출력을 평가. 반드시 분류(PASS/FAIL) 판정으로 사용해야 신뢰성 확보 | JUnit assertTrue/assertFalse. 점수(73점)가 아닌 통과/실패 판정으로 평가 |
| 컨텍스트 엔지니어링 | 모델 입력 컨텍스트 윈도우의 예산을 체계적으로 설계/관리. 시스템 프롬프트 + 도구 정의 + 대화 이력 + RAG 결과의 비율 설계 | application.yml 설정 설계. DB pool, thread pool, cache 크기를 전체 메모리 예산 내에서 설계하는 것 |
| LoRA | Low-Rank Adaptation. 원본 가중치를 동결하고 저랭크 행렬 어댑터(A×B)만 학습. 전체 파라미터의 0.1~1%만 수정 | AOP @Around 어드바이스. 원본 코드(가중치)는 안 건드리고 횡단 관심사(어댑터)만 추가 |
| 파멸적 망각 | 파인튜닝으로 특정 도메인을 학습하면 기존에 알던 일반 지식이 손상되는 현상. 전체 파라미터 수정 시 심화 | 라이브러리 버전 업그레이드 시 기존 기능 깨짐. dependency 충돌로 다른 모듈이 망가지는 것 |
| 지식 증류 | 큰 모델(선생)의 출력/로짓을 작은 모델(학생)에 전달하여 학습. 현실적으로는 합성 데이터 기반 SFT가 주류 | 시니어 개발자가 쓴 코드 예제(합성 데이터)로 주니어가 학습. 모든 사고방식(로짓)을 전달하는 건 비현실적 |
| vLLM | PagedAttention 기반 고처리량 추론 엔진. HuggingFace 대비 최대 24배 처리량. 프로덕션 배포 표준 | Tomcat 대신 Netty. 같은 모델이라도 서빙 엔진에 따라 처리량이 수십 배 차이 |
| Responses API | OpenAI의 Chat Completions 대체 차세대 API. 4개 롤(developer, user, assistant, tool)로 구조 변경 | Spring MVC → Spring WebFlux 전환. 기존 API를 더 유연한 새 API로 마이그레이션 |
| n8n | 에이전틱 AI 비주얼 빌더 플랫폼. 노드 기반 워크플로우로 AI 에이전트 구성. 코드 없이 복잡한 AI 파이프라인 구축 가능 | Spring Integration/Apache Camel의 비주얼 버전. 드래그앤드롭으로 통합 파이프라인 구성 |
| MCP | Model Context Protocol. AI 모델이 외부 도구/데이터에 접근하는 표준 프로토콜. Anthropic 주도, 업계 표준화 진행 중 | JDBC/JPA 인터페이스. DB 종류와 무관하게 동일한 인터페이스로 접근하는 것과 동일한 개념 |
| RAG | Retrieval-Augmented Generation. 외부 문서를 검색하여 LLM 컨텍스트에 주입 후 생성. 할루시네이션 감소 효과 | @Autowired로 외부 서비스 주입. 모델 혼자 답하지 않고 외부 지식(DB)을 주입받아 답변 |
| 에이전트 | LLM이 도구를 사용하여 스스로 계획-실행-검증을 반복하는 자율 시스템. ReAct 패턴이 기본 | 스프링 배치 Step. 조건부 분기 + 외부 API 호출 + 결과 검증을 자동으로 반복 실행 |
부록 B. 비교표 모음
각 비교표에 Java/Spring 비유와 선택 가이드를 추가하여 실무 판단에 도움이 되도록 정리했습니다.
B-1. 모델 튜닝 기법
| 기법 | 방식 | 비용 | 효과 | Java 비유 | 언제 쓰나? |
|---|---|---|---|---|---|
| SFT | 정답 (Q,A) 쌍 데이터로 출력 방향 조정 | 중간 | 기본. 모든 튜닝의 출발점 | application.yml 오버라이드 |
도메인 특화 응답 패턴이 필요할 때 (의료, 법률, 금융) |
| RLHF | 인간 선호도 → 보상 모델 학습 → PPO로 최적화 | 높음 | 인간 선호도 정밀 반영 | QA팀 피드백 → SonarQube 규칙 → 자동 수정 파이프라인 | 안전성, 정치적 올바름 등 미묘한 선호도 조정 (대형 기업용) |
| DPO | 보상 모델 없이 (선택,거부) 쌍의 로그 확률 차이 직접 최적화 | 낮음 | RLHF급. 보상 모델 불필요로 파이프라인 단순화 | A/B 테스트 결과로 바로 코드 수정 (별도 평가 시스템 불필요) | 현재 가장 추천. RLHF 효과를 적은 비용으로 원할 때 |
| LoRA | 원본 동결 + 저랭크 어댑터(A×B)만 학습. 전체의 0.1~1% | 최저 | 경량 튜닝. 여러 어댑터 교체 가능 | @Around AOP 어드바이스. 원본 코드는 그대로, 횡단 관심사만 추가 |
GPU 1~2장으로 빠르게 도메인 적응할 때. 가장 실용적 |
실무 추천 경로: LoRA로 시작 → 성능 부족 시 SFT → 선호도 조정 필요 시 DPO 추가 Spring 비유:
@Profile설정부터 시작 → 불충분하면 커스텀 빈 → 최종적으로 프레임워크 레벨 수정
B-2. 위치 인코딩 비교
| 기법 | 원리 | 외삽 능력 | 현재 상태 | Java 비유 | 핵심 포인트 |
|---|---|---|---|---|---|
| 절대 PE | 위치를 고정 벡터로 더하기 | 불가 (학습 범위 초과 시 붕괴) | 폐기됨 | array[index] — 배열 크기 넘으면 IndexOutOfBoundsException |
초기 트랜스포머(BERT)에서 사용. 이제 쓰지 않음 |
| RoPE | 위치를 벡터 회전각으로 인코딩. 상대 위치가 내적에 반영 | 학습 범위 내에서만 유효 | 현재 기반 기술 | Collections.rotate() — 회전하면 상대 위치 보존 |
GPT-NeoX, LLaMA 등 대부분 모델의 기본 |
| ALiBi | 거리에 비례하는 선형 페널티 부여 | 긴 거리에서 성능 저하 (트레이드오프) | 거의 안 씀 | 거리에 따른 @Timeout — 멀수록 타임아웃 적용 |
아이디어는 좋았으나 실제 성능에서 밀림 |
| LongRoPE | 고주파(단거리)와 저주파(장거리) 차원을 분리하여 차등 스케일링 | 우수 (128K+ 지원) | 현재 주류 | L1 캐시(로컬)와 Redis(원격)를 별도 TTL로 관리 | 대부분 장문맥 모델이 채택. 가장 실용적 |
| YaRN | 소프트맥스 템퍼처 보정으로 RoPE 외삽 안정화 | 보조적 효과 | LongRoPE 보조 | Comparator 정규화 — 비교 기준을 조정하여 안정성 향상 |
LongRoPE와 함께 쓰면 시너지 |
한줄 요약: RoPE가 기본 → LongRoPE로 확장 → YaRN으로 보정. 이 3단 콤보가 현재 표준.
B-3. 인퍼런스 비용 절감
| 순위 | 전략 | 효과 | Java 비유 | 적용 난이도 | 설명 |
|---|---|---|---|---|---|
| 1 | UI로 호출 자체 감소 | 최대 | DB 조회만으로 해결되면 외부 API를 안 부르는 것 | 쉬움 | 벡터 DB 검색 결과를 사이드바에 표시 → 사용자가 클릭으로 해결 |
| 2 | 벡터 DB 캐시 (유사도 0.97+) | 대 | Redis 캐시 히트. DB까지 안 가도 됨 | 쉬움 | 이전 답변과 유사한 질문이면 LLM 호출 없이 캐시된 답변 제시 |
| 3 | vLLM (파이프라이닝) | 대 | Tomcat → Netty 전환. Connection Pool + 비동기 | 중간 | PagedAttention으로 100개 요청을 20~30초에 처리 |
| 4 | 양자화 (FP16→INT8/FP8) | 중 | double→float 다운캐스팅. 메모리 절반 |
쉬움 | GPTQ/AWQ로 모델 크기 50% 절감. PPL 확인 필수 |
| 5 | KV 캐시 | 중 | HashMap 캐시. 이전 계산 결과 재활용 |
자동 | 대부분 프레임워크가 자동 적용. 메모리만 충분하면 됨 |
| 6 | Flash Attention | 중 | L1 캐시에서 직접 계산 (RAM 왕복 제거) | 자동 | vLLM, HF Transformers에서 자동 활성화 |
| 7 | 프리픽스 캐시 | 소~중 | @Cacheable — 공통 시스템 프롬프트 KV 캐시 재활용 |
중간 | RAG/멀티턴에서 공유 프롬프트가 긴 경우 효과적 |
실무 적용 순서: 1~2번(비용 제로)부터 시작 → 3번(vLLM 전환) → 4번(양자화) → 나머지는 자동 적용 Spring 비유: 먼저 캐시 전략 → 서버 튜닝(Netty) → JVM 옵션 최적화 → 나머지는 프레임워크가 알아서
B-4. 아키텍처 패턴 비교 (추가)
| 패턴 | 핵심 개념 | 장점 | 단점 | Java 비유 |
|---|---|---|---|---|
| 트랜스포머 | 셀프 어텐션(O(N²))으로 모든 토큰 간 관계 계산 | 정밀한 장거리 의존성 | 긴 시퀀스에서 메모리 폭발 | for 중첩 루프 — 모든 쌍을 비교 |
| 맘바(SSM) | 상태 변수로 시퀀스를 O(N) 선형 처리 | 긴 시퀀스 효율적 | 정밀 어텐션 부족 | Stream.reduce() — 누적 상태로 처리 |
| 잠바(Jamba) | 맘바 + 트랜스포머 하이브리드 | 둘의 장점 결합 | 구현 복잡도 | WebFlux + @Transactional 혼합 |
| RAG | 외부 검색 + LLM 생성 | 최신 정보 반영, 할루시네이션 감소 | 검색 품질에 의존 | @Autowired 외부 서비스 주입 |
| 에이전트 | LLM + 도구 + 계획/실행 루프 | 복잡한 작업 자동화 | 비용, 지연, 제어 어려움 | Spring Batch — 조건부 분기 + 외부 호출 + 검증 반복 |
부록 C. 참고 링크
각 링크에 무엇을 얻을 수 있는지와 관련 에피소드를 표시했습니다.
C-1. 공식 문서 & 도구
| 링크 | 설명 | 관련 EP |
|---|---|---|
| OpenAI Responses API 가이드 | Chat Completions → Responses API 마이그레이션 가이드. 4롤 구조, 웹 검색/파일 검색 빌트인 도구 | EP15 |
| vLLM 공식 문서 | PagedAttention, 인퍼런스 최적화, 양자화 배포 가이드. 프로덕션 서빙 필수 | EP20 |
| 라마 팩토리 | 설치형 LoRA/SFT/DPO 튜닝 도구. 웹 UI로 코드 없이 파인튜닝 가능. 초보자에게 가장 추천 | EP19, EP20 |
| n8n | 에이전틱 AI 비주얼 빌더. 노코드로 AI 에이전트 워크플로우 구성. Spring Integration 비주얼 버전 | EP16 |
| MCP 표준 | Model Context Protocol 공식 스펙. AI 도구 연동의 JDBC 같은 표준 인터페이스 | EP14, EP15 |
| LangSmith | LLM 파이프라인 트레이싱, 평가, 모니터링. Spring Actuator + Zipkin의 LLM 버전 | EP10, EP11 |
C-2. 평가 & 벤치마크
| 링크 | 설명 | 관련 EP |
|---|---|---|
| RAGAS | RAG 파이프라인 평가 프레임워크. Faithfulness, Relevancy 등 자동 메트릭 | EP10, EP11 |
| MTEB 리더보드 | 임베딩 모델 성능 비교. 한국어 모델 선택 시 필수 참조 | EP11 |
C-3. 논문 & 학습 자료
| 링크 | 설명 | 관련 EP |
|---|---|---|
| DPO 논문 | Direct Preference Optimization 원본 논문. 보상 모델 없이 직접 선호도 최적화하는 수학적 증명 | EP6 |
| 컨텍스트 엔지니어링 가이드 | 프롬프트 엔지니어링 → 컨텍스트 엔지니어링 진화. 토큰 예산 설계 실무 가이드 | EP12 |
| Attention Is All You Need | 트랜스포머 원본 논문. 셀프 어텐션, 멀티헤드 어텐션의 수학적 기초 | EP2 |
| LoRA 논문 | Low-Rank Adaptation 원본 논문. 저랭크 분해로 효율적 파인튜닝하는 핵심 아이디어 | EP19 |
| Flash Attention 논문 | IO-Aware 어텐션 알고리즘. GPU 메모리 계층을 활용한 최적화 | EP2 |
| Mamba 논문 | Selective State Space Model. 트랜스포머의 O(N²) 한계를 O(N)으로 극복 | EP4 |
클릭하거나 Space를 눌러 뒤집기